Odpowiedzi:
Zakładając, że każda z linii zawiera „słowo” znaków,
i nie mamy nic przeciwko temu, aby powłoka wykonała trochę więcej pracy,
oto rozwiązanie AWK.
# Niech twój tekst będzie w `str.txt` awk '{długość wydruku (1 $), 1 $}' str.txt | sort -nk 1 | głowa -1 # Wyjście: 2 gf ## Który jest najkrótszym ciągiem
Możesz to zoptymalizować, aby uniknąć sortowania za pomocą większej ilości AWK.
Możesz dostosować to jeszcze bardziej, jeśli masz więcej niż jedno „słowo” w wierszu.
Pamiętaj również, że jeśli masz wiele najkrótszych ciągów, da ci to jeden z nich.
Możesz też zrobić więcej sztuczek, aby je zdobyć.
Awk jest do tego świetny:
awk '(NR == 1 || length < length(shortest)) { shortest = $0 } END { print shortest }'
Pierwsza część ustawia „najkrótszą” zmienną na bieżącą linię, jeśli jest to pierwsza linia lub jeśli długość jest krótsza niż poprzednio najkrótsza linia. Wreszcie ostatnia część wypisuje wartość najkrótszego.
BASH wpis nr 1 mówi, jak czytać plik linia po linii. ${#foo}
da ci długość $foo
. Wystarczy zapętlić, testując kolejno każdą linię.
Rozwiązanie wykorzystujące sed i utrzymujące pierwszą najkrótszą linię z pliku:
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
Aby zachować ostatnią najkrótszą linię z pliku:
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
Poniżej znajduje się wyjaśniona wersja 1. najkrótszej linii w postaci pliku skryptu sed, który można uruchomić za pomocą 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
Oto moja dość niezdarna oferta za pomocą Perla:
grep . file | perl -E '@a=<>; @s = sort {length $a <=> length $b}@a; say $s[0] . "Line $."; '
Nieco łatwiej: perl -ne '$ l = $ _ if $. == 1; $ l = $ _ jeśli długość ($ ) <długość ($ l); END {print $ l;} 'plik ### najkrótszy perl -ne' $ l = $ if $. == 1; $ l = $ _ jeśli długość ($ _)> długość ($ l); END {print $ l;} 'najdłużej plik ###
grep plik | perl -ne '$ l = $ _ if $. == 1; $ l = $ _ jeśli długość ($ _) <długość ($ l); END {print $ l;} '## najkrótsze usunięcie możliwych pustych linii
grep plik | perl -ne '$ l = $ _ if $. == 1; $ l = $ _ jeśli długość ($ _) <długość ($ l); END {print $ l;} '## najdłużej usuwając możliwe puste linie
$0
(pełna linia) zamiast$1
(pierwsze pole).$1
powróci tylko do pierwszej białej spacji. Przykład SpawnST nie ma żadnych spacji, więc albo działałby, gdyby jego prawdziwy plik danych był taki sam.