Як я можу визначити рядки у файлах певної довжини


12

Я хотів би знайти в коді рядки, які перевищують певну довжину. Мій код у кількох файлах. Який хороший спосіб це зробити?

Я хотів би знати файли та номери рядків; зміст буде кращим, але не необхідним. Мета вправи полягає в тому, щоб потім з'ясувати, як ламати лінії (можливо, вручну).


Як ви хочете отримати результати? Як самі рядки (їх вміст, як у grep), або як номери рядків, або як щось інше (можливо, ви хочете застосувати до них ще одну дію)? Напевно, найзручніший спосіб зробити це залежить від того, що буде зроблено з цими рядками далі.
imz - Іван Захарящев

@ imz - ІванЗахарящев Добрий момент. Питання оновлено.
Марцін

Відповіді:


13

З grep:

grep -En '.{12}' file

Для рядків довжиною не менше 12 символів.

З кількома файлами:

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

Деякі grepреалізації, такі як GNU grep, можуть самі знайти файл.

grep -rEn '.{12}' .

Але остерігайтеся символьних посилань та інших нестандартних файлів.


Мені це подобається, тому що це просто, і я сподівався зробити щось подібне (досі не обійшлося).
Marcin

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 awk до недавнього часу був тим, де це не працювало, якщо ви не передасте POSIXLY_CORRECT в його середовище).
Стефан Шазелас

5

Оскільки одне, чого бракувало, було sedрішенням

sed -n '/^.\{6,\}/p' file

5

Рішення Баша

#!/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
Додано кілька хороших практик. Також врахуйте, що новий рядок не враховується, $lineтому не потрібно віднімати його.
iruvar

2
@ 1_CR насправді, якщо ви не дасте readім'я для читання, він прочитає REPLYі включить увесь пробіл. Не IFSпотрібно налаштування.
kojiro

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

3
Ви повинні додати -lкомандний рядок, perlбуде рахувати розрив рядка у ваших рядках.
cuonglm

1

Ruby:

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

Пітон:

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[@]}"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.