bash echo количество строк файла, заданных в переменной bash без имени файла

79

У меня есть следующие три конструкции в сценарии bash:

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE)
echo $NUMOFLINES" lines"

echo $(wc -l $JAVA_TAGS_FILE)" lines"

echo "$(wc -l $JAVA_TAGS_FILE) lines"

И оба они производят идентичный вывод при запуске скрипта:

121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines
121711 /home/slash/.java_base.tag lines

Т.е. имя файла тоже отображается эхом (чего я не хочу). Почему эти скрипты не работают и как мне вывести чистый:

121711 lines

?

Марк Юний Брут
источник
Возможный дубликат получения целого числа из wc в bash
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

157

Пример использования ваших собственных данных

Вы можете избежать включения вашего имени файла в переменную NUMOFLINES , используя перенаправление из JAVA_TAGS_FILE , вместо того, чтобы передавать имя файла в качестве аргумента в wc . Например:

NUMOFLINES=$(wc -l < "$JAVA_TAGS_FILE")

Объяснение: Используйте каналы или перенаправление, чтобы избежать имен файлов в выводе

Туалет утилита не будет печатать имя файла в его выходе , если входные данные берутся от оператора трубы или перенаправления. Рассмотрим эти различные примеры:

# wc shows filename when the file is an argument
$ wc -l /etc/passwd
41 /etc/passwd

# filename is ignored when piped in on standard input
$ cat /etc/passwd | wc -l
41

# unusual redirection, but wc still ignores the filename
$ < /etc/passwd wc -l
41

# typical redirection, taking standard input from a file
$ wc -l < /etc/passwd
41

Как видите, wc печатает имя файла только тогда, когда оно передается как аргумент, а не как данные на стандартный ввод. В некоторых случаях может потребоваться напечатать имя файла, поэтому полезно понимать, когда оно будет отображаться.

Тодд А. Джейкобс
источник
1
помните, что этот подход не будет включать последнюю строку, если последняя строка не заканчивается символом конца строки. Смотрите мое исправление ниже.
ling
15

wc не может получить имя файла, если вы его не укажете.

wc -l < "$JAVA_TAGS_FILE"
Игнасио Васкес-Абрамс
источник
2
Ну тогда не надо. Просто передайте файл на стандартный wcввод, как показано в ответе. Так cat "$JAVA_TAGS_FILE" | wc -lили, что то же самое, wc -l < "$JAVA_TAGS_FILE". Таким образом, будут wcполучены только необработанные данные, а не имя файла.
Witiko 04
12

Вы также можете использовать awk:

awk 'END {print NR,"lines"}' filename

Или же

awk 'END {print NR}' filename

Хавьер Лопес
источник
5

(применимо к Mac и, возможно, к другим Unix)

На самом деле есть проблема с подходом wc: он не считает последнюю строку, если она не заканчивается символом конца строки.

Используйте это вместо

nbLines=$(cat -n file.txt | tail -n 1 | cut -f1 | xargs)

или даже лучше (спасибо gniourf_gniourf):

nblines=$(grep -c '' file.txt)

Примечание. Подход awk от chilicuil также работает.

лин
источник
2
Очень замысловатый метод! Может быть, вы захотите nblines=$(grep -c '' file)вместо этого (в данном случае это канонический способ подсчета неполных строк). Однако обратите внимание, что согласно POSIX вы учитываете неполные строки (а не строки ). Фактически вы имеете дело с двоичным файлом, а не с текстовым файлом .
gniourf_gniourf
@gniourf_gniourf Спасибо, я не знал об этом, он отлично работает и даже более лаконичен.
ling
это может быть лучшее решениеnblines=$(($(cat "file.txt" | wc -l) + 1))
Андрей Изман
3

Это очень просто:

NUMOFLINES=$(cat $JAVA_TAGS_FILE | wc -l )

или же

NUMOFLINES=$(wc -l $JAVA_TAGS_FILE | awk '{print $1}')
Слава Семушин
источник
Первый - бесполезное использование кота.
кап
@kap Нет, только так выглядит. Если вы избавитесь от него cat, у вас будет второй пример, потому что он wc -lвозвращает 2 столбца, когда он используется только с файлом.
Слава
-3

Обычно я использую функцию «обратного тика» в bash

export NUM_LINES=`wc -l filename`

Обратите внимание, что «галочка» - это «обратная галочка», например, «не обычная одинарная кавычка».

Русь Хор
источник
5
Это просто другая нотация, которая не решает проблему того, что имя файла является частью результата.
Иззи