Знайдіть будь-які лінії, що перевищують певну довжину


Відповіді:


89

У порядку зменшення швидкості (в системі GNU в локалі UTF-8 та на вході ASCII) відповідно до моїх тестів:

grep '.\{80\}' file

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

awk 'length>79' file

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

За винятком perl¹ одного (або для awk/ grep/ sedреалізацій (наприклад, mawkабо зайнятої області), які не підтримують багатобайтові символи), він рахує довжину в кількості символів (відповідно до 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інструментів та GNU, у вас все ще будуть потенційні проблеми для рядків, що містять символи NUL (0x0 байт).


¹ Хоча на perlповедінку може впливати PERL_UNICODEзмінна середовища


Що ви маєте на увазі під "ефективним"?
rowantran

Я думаю, що маніпуляція означає ефективність введення тексту. awkможе підійти ближче, якщо ви кинете ($0), що все одно неявне;).
Тор

9
BTW, якщо прив’язати регулярний вираз до початку рядка ^, це трохи швидше: наприклад 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

Шелл підхід:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.