Jak uzyskać najkrótszy ciąg w pliku tekstowym z powłoką

3

Załóżmy, że mam plik tekstowy jak poniżej

abcd
aaaaaaa
gfgk
hahahahahahhahh
gf

Wtedy gfzostaną zwrócone. Jakieś dobre pomysły?

SpawnST
źródło

Odpowiedzi:

7

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ć.

nik
źródło
Podoba mi się to, ale powinno używać $0(pełna linia) zamiast $1(pierwsze pole). $1powró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.
Doug Harris
@Doug, odsyłam do pierwszego zdania odpowiedzi :-)
nik.
Ups, przepraszam, że przegapiłem twoje założenie. Zresztą i tak odpowiedziałem już na twoją odpowiedź.
Doug Harris
10

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.

Bkkbrad
źródło
Niesamowite, dodane do skrzynki narzędziowej.
l0b0
3

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ę.

Ignacio Vazquez-Abrams
źródło
2

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
jfg956
źródło
+1, ponieważ jeśli spojrzysz bardzo uważnie i wystarczająco długo na ten scenariusz, możesz zobaczyć kobietę w czerwonej sukience ...
Michael
0

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

Paul-Gerhard Woolcock
źródło