Как получить самую короткую строку в текстовом файле с оболочкой

4200
SpawnST

Предположим, у меня есть текстовый файл, как показано ниже

abcd aaaaaaa gfgk hahahahahahhahh gf 

Тогда gfбудут возвращены. Есть хорошие идеи?

3

5 ответов на вопрос

10
Bkkbrad

Awk отлично подходит для этого:

awk '(NR == 1 || length < length(shortest)) { shortest = $0 } END { print shortest }' 

Первая часть устанавливает «самую короткую» переменную для текущей строки, если она является первой строкой или если длина короче самой короткой строки, замеченной ранее. Наконец, последняя часть выводит значение кратчайшего.

Круто, добавлено в ящик для инструментов. l0b0 13 лет назад 0
7
nik

Предполагая, что каждая строка содержит «слово» символов,
и мы не против позволить оболочке выполнить немного больше работы,
вот решение AWK.

# Пусть ваш текст будет в `str.txt`  awk '' str.txt | сортировать -nk 1 | голова -1  # Вывод: 2 gf ## Какая самая короткая строка 

Вы можете оптимизировать это, чтобы избежать сортировки с еще большим количеством AWK.
Вы можете изменить это далее, если у вас есть более одного слова в строке.

Также обратите внимание, что если у вас есть несколько самых коротких строк, это даст вам одну из них.
Вы можете сделать еще несколько трюков, чтобы получить их тоже.

Мне нравится это, но он должен использовать `$ 0` (полная строка) вместо` $ 1` (первое поле). `$ 1` вернется только до первого пробела. В примере SpawnST нет пробелов, поэтому любой из них будет работать, если его реальный файл данных будет таким же. Doug Harris 14 лет назад 0
@ Дуг, я отсылаю вас к открытию предложения ответа :-) nik 14 лет назад 0
Ой, прости, я пропустил твою линию предположений. Я уже дал ваш ответ в любом случае. Doug Harris 14 лет назад 0
3
Ignacio Vazquez-Abrams

BASH FAQ # 1 рассказывает о том, как построчно читать файл. ${#foo}даст вам длину $foo. Просто цикл, тестирование каждой строки по очереди.

2
jfg956

Решение с использованием sed и сохранением 1-й кратчайшей строки из файла:

sed -e '1h;H;g;s/[^\n]/#/g;s/\(#*\)\n\1/\n/;G;/^\n/s/\n.*\n\(.*\)\n.*/\1/;s/.*\n//;h;$!d' your_file 

Чтобы сохранить последнюю короткую строку из файла:

sed -e '1h;G;h;s/[^\n]/#/g;s/\(#*\)\n\1/\n/;G;/^\n/s/\n.*\n\(.*\)\n.*/\1/;s/.*\n//;h;$!d' your_file 

Ниже представлен вариант первой кратчайшей строки в виде файла сценария sed, который можно запустить с помощью sed -f script your_file:

# The hold space will contain the shortest line at the beginning and the ending of each cycle. # The 1st line is the shortest, so put it in the hold space so an empty line will not be returned. 1h # Append the current line to the shortest so far, remember these 2 lines in the hold space, and take a copy in the pattern space to work on them. H;g # Replace all chars by #. s/[^\n]/#/g # Delete the same number of # before and after the line delimiter. s/\(#*\)\n\1/\n/ # Append the 2 lines remembered in the hold space to the pattern space. G # If the hold space begin by a '\n', the current line was shorter, so keep it. /^\n/s/\n.*\n\(.*\)\n.*/\1/ # Else, the previous line was shorter, so keep it. s/.*\n// # Remember shortest in hold space. h # If last line, print it (delete everything else). $!d 
+1 потому что если вы посмотрите очень внимательно и достаточно долго на этот сценарий sed, вы можете увидеть женщину в красном платье ... michael 11 лет назад 0
0
Paul-Gerhard Woolcock

Вот мое довольно неуклюжее предложение с использованием Perl:

grep . file | perl -E '@a=<>; @s = sort @a; say $s[0] . "Line $."; ' 

Несколько проще: perl -ne '$ l = $ _ if $. == 1; $ l = $ _, если длина ($ ) <длина ($ l); END 'file ### кратчайший perl -ne' $ l = $ if $. == 1; $ l = $ _ if length ($ _)> length ($ l); END 'file ### longest

grep. файл | perl -ne '$ l = $ _ if $. == 1; $ l = $ _, если длина ($ _) <длина ($ l); END '## кратчайшее удаление возможных пустых строк

grep. файл | perl -ne '$ l = $ _ if $. == 1; $ l = $ _, если длина ($ _) <длина ($ l); END '## самое длинное удаление возможных пустых строк

Похожие вопросы