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

?


Ответы:


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


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
Это просто другая нотация, которая не решает проблему того, что имя файла является частью результата.
Иззи
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.