Найти любые строки, превышающие определенную длину

53

Можно ли найти какие-либо строки в файле, которые превышают 79 символов?

rowantran
источник

Ответы:

91

В порядке уменьшения скорости (в системе GNU в локали UTF-8 и на входе ASCII) согласно моим тестам:

grep '.\{80\}' file

perl -nle 'print if length$_>79' file

awk 'length>79' file

sed -n '/.\{80\}/p' file

За исключением perl¹ one (или для awk/ grep/ sedреализаций (например, mawkили busybox), которые не поддерживают многобайтовые символы), он считает длину в терминах количества символов (в соответствии с LC_CTYPEнастройкой локали) вместо байтов .

Если во входных данных есть байты, которые не образуют часть допустимых символов (что иногда случается, когда набор символов локали UTF-8, а входные данные находятся в другой кодировке), то в зависимости от решения и реализации инструмента эти байты будет считаться как 1 символ или 0 или не совпадать ..

Например, строка, состоящая из 30 asa 0x80 байтов, 30 bs, 0x81 байтов и 30 UTF-8 és (кодированных как 0xc3 0xa9), в локали UTF-8 не будет совпадать .\{80\}с GNU grep/ sed(так как этот автономный байт 0x80 не соответствует .), будет иметь длину 30 + 1 + 30 + 1 + 2 * 30 = 122 с perlили mawk, 3 * 30 = 90 с gawk.

Если вы хотите посчитать в байтах, исправьте локаль с Cпомощью LC_ALL=C grep/awk/sed....

Это будет иметь все 4 решения, учитывая, что строка выше содержит 122 символа. За исключением perlинструментов in и GNU, у вас все еще могут возникнуть проблемы со строками, содержащими символы NUL (0x0 байт).


Variable на perlповедение может повлиять PERL_UNICODEпеременная окружения, хотя

manatwork
источник
Что вы подразумеваете под "эффективными"?
rowantran
Я думаю, что manatwork означает эффективность печати. awkможет подойти ближе, если уронить ($0), что в любом случае неявно;).
Тор
9
Кстати, если вы прикрепите регулярное выражение к началу строки с помощью ^, это немного быстрее: например grep '^.\{80\}' file.
Cas
4
Решение Perl не учитывает кодирование с переменным размером, например UTF-8, в отличие от всех других решений.
BatchyX
6
Достаточно большие значения N терпят неудачу с grep, но преуспевают с awk. (например, grep '^.\{1000\}' fileвозвращается grep: invalid repetition count(s), пока awk 'length>1000' fileуспешно.)
mdahlman
1

Shell подход:

while IFS= read -r line || [ -n "$line" ];
do 
    [ "${#line}" -gt 79 ] && printf "%s\n" "$line"
done < input.txt

Python подход:

python -c 'import sys;f=open(sys.argv[1]);print "\n".join([ l.strip() for l in f if len(l) >79 ]);f.close()' input.txt

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

#!/usr/bin/env python
import sys

with open(sys.argv[1]) as f:
    for line in f:
        if len(line) > 79:
            print line.strip()

Если мы хотим , чтобы исключить символ новой строки \nиз расчетов, мы можем сделать if len(line) > 79бытьif len(line.strip()) > 79

Примечание: это синтаксис Python 2.7. Используйте print()для Python 3

Сергей Колодяжный
источник