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.