Я хотел бы напечатать количество символов в каждой строке текстового файла с помощью команды unix. Я знаю, что с PowerShell это просто
gc abc.txt | % {$_.length}
но мне нужна команда unix.
Ответы:
Используйте Awk.
awk '{ print length }' abc.txt
while IFS= read -r line; do echo ${#line}; done < abc.txt
Это POSIX, поэтому он должен работать везде.
Изменить: добавлен -r, предложенный Уильямом.
Изменить: остерегайтесь обработки Unicode. Bash и zsh с правильно установленной локалью покажут количество кодовых точек, но тире покажет байты, поэтому вам нужно проверить, что делает ваша оболочка. Кроме того, в Юникоде есть много других возможных определений длины, так что это зависит от того, что вы действительно хотите.
Изменить: префикс с, IFS=
чтобы избежать потери начальных и конечных пробелов.
IFS=
на read
команду , когда требуется , чтобы читать в произвольных данных. Итак IFS= read -r
. read
использует IFS
разделение слов для выполнения, и хотя все разделенные слова затем вставляются обратно вместе в одну доступную переменную ( line
), нет гарантии, что они будут вставлены обратно вместе со всеми исходными символами-разделителями, которые у них были, или только с одним потенциально другим ед. Например, при использовании IFS по умолчанию строка foo bar
может стать без foo bar
7 пробелов. (Например, как Stack Overflow потерял соседние пробелы в этой строке примера в этом комментарии).
IFS
нужно настроить, но проблема, когда это не так, более тонкая.
Я пробовал другие ответы, перечисленные выше, но они очень далеки от достойных решений при работе с большими файлами, особенно когда размер одной строки занимает более ~ 1/4 доступной оперативной памяти.
И bash, и awk проглатывают всю строку, хотя для этой проблемы это не нужно. Bash выдаст ошибку, если строка станет слишком длинной, даже если у вас достаточно памяти.
Я реализовал чрезвычайно простой, довольно неоптимизированный скрипт python, который при тестировании с большими файлами (~ 4 ГБ на строку) не хлюпает, и это намного лучшее решение, чем приведенные.
Если это критический по времени код для производства, вы можете переписать идеи на C или выполнить лучшую оптимизацию в вызове чтения (вместо чтения только одного байта за раз), после проверки того, что это действительно узкое место.
Код предполагает, что новая строка является символом перевода строки, что является хорошим предположением для Unix, но YMMV в Mac OS / Windows. Убедитесь, что файл заканчивается переводом строки, чтобы не пропустить счетчик символов последней строки.
from sys import stdin, exit
counter = 0
while True:
byte = stdin.buffer.read(1)
counter += 1
if not byte:
exit()
if byte == b'\x0a':
print(counter-1)
counter = 0
Вот пример использования xargs
:
$ xargs -d '\n' -I% sh -c 'echo % | wc -c' < file
Попробуй это:
while read line
do
echo -e |wc -m
done <abc.txt
echo -e | wc -m
, не так ли? Бесполезное использование команд; оболочка может подсчитывать символы в переменной. Плюс echo -e
полностью несовместим и работает в половине оболочек, в то время как запуск с одной escape-последовательностью работает в других и ничего в остальных.