3

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

abcd
aaaaaaa
gfgk
hahahahahahhahh
gf

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

5 ответов5

10

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

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

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

7

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

# Let your text be in `str.txt`

awk '{print length($1), $1}' str.txt | sort -nk 1 | head -1

# Output: 2 gf ## Which is the shortest string

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

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

3

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

2

Решение с использованием 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
0

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .