Как я могу определить строки в файлах более определенной длины

12

Я хотел бы найти строки в моем коде, которые превышают определенную длину. Мой код находится в нескольких файлах. Какой хороший способ сделать это?

Я хотел бы знать файлы и номера строк; содержание было бы предпочтительным, но не обязательно. Цель упражнения - выяснить, как разбить линии (возможно, вручную).

Marcin
источник
Как вы хотите результаты? Как сами строки (их содержание, как в grep), или как номера строк, или как что-то еще (возможно, вы хотите применить к ним другое действие)? Вероятно, наиболее удобный способ сделать это зависит от того, что будет сделано с этими строками дальше.
imz - Иван Захарящев,
@ imz - IvanZakharyaschev Хороший вопрос. Вопрос обновлен.
Марцин,

Ответы:

13

С grep:

grep -En '.{12}' file

Для строк длиной не менее 12 символов.

С несколькими файлами:

find . -type f -exec grep -En '.{12}' {} +

Некоторые grepреализации, такие как GNU grep, могут сами находить файлы.

grep -rEn '.{12}' .

Но остерегайтесь символических ссылок и других нестандартных файлов.

Стефан Шазелас
источник
Мне это нравится, потому что это просто, и я надеялся сделать что-то подобное (до сих пор не удосужился об этом).
Марцин
12

Решение AWK

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

Или, более кратко:

awk 'length > 5' file
Рамеш
источник
9
Мы можем сократить вашу версиюawk 'length > 5'
cuonglm
Gnouc - убийца фигурных скобок;)
Ouki
1
+1 дляawk 'length > 5'
3
С GNU awkнесколько менее элегантный, но лаконичныйawk '/^.{6,}/'
iruvar
3
@ 1_CR, это POSIX, и его можно сократить до awk '/.{6}/'(на самом деле, GNU до недавнего времени раньше не работал, если вы не передадите POSIXLY_CORRECT в его среду).
Стефан Шазелас
5

Поскольку единственное, чего не хватало, было sedрешением

sed -n '/^.\{6,\}/p' file
Iruvar
источник
5

Решение Bash

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

Так, например ./whatever.sh < input.file. Это не включает перевод строки путем вычитания 1 из $len; если это нежелательно, или ваш ввод использует окончания CRLF, вы должны соответствующим образом настроить.

лютик золотистый
источник
1
почему бы не ${#line}избежать exprразвилки?
iruvar
1
ха-ха, +1 для чистого bashрешения. Но учтите, что, если вы не встанете IFS=перед собой read, начальные пробелы будут игнорироваться.
iruvar
1
Добавлено несколько хороших практик Bash. Также обратите внимание, что перевод строки не учитывается, $lineпоэтому нет необходимости вычитать его.
iruvar
2
@ 1_CR на самом деле, если вы не дадите readимя для чтения, оно будет читать REPLYи включать все пробелы. Нет IFSне требуется установка.
Кодзиро
2
Это будет очень медленно и обрабатывает символы обратной косой черты. while readциклы для обработки текста действительно плохая практика.
Стефан Шазелас
4

С помощью perl(например), при условии, что вы ищете строки длиной более 80 символов:

Чтобы отобразить строки:

$ perl -nle 'print if length > 80' your_file

Чтобы отобразить номер строки:

$ perl -nle 'print "$.\n" if length > 80' your_file

Или оба:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file
Ouki
источник
3
Вы должны добавить -lкомандную строку, perlбудет считать разрыв строки в ваших строках.
cuonglm
1

Рубин :

ruby -lne 'puts $_ if $_.size > 5' intputfile

Python:

python -c "import sys;[ sys.stdout.write(''.join(line)) for line in sys.stdin if len(line.strip()) > 5 ]" < inputfile
Рахул Патил
источник
1

Вот еще одно решение для bash (bash 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

Полученный массив является разреженным, поэтому индексы массива сохраняются. Поскольку мы начали с 1, индексы - это номера строк, которые мы сохранили. Мы можем вывести только эти номера строк:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

Или мы можем вывести сами строки:

printf '%s\n' "${MAPFILE[@]}"
Кодзиро
источник