Wiersz polecenia: wyodrębnij podciąg z danych wyjściowych

25

Powiedz, że uruchomiłem polecenie SayStuff

$ SayStuff

i wynik jest

Watermelons and cucumbers

Teraz. Powiedzmy, że chcę wyodrębnić podciąg cucumbersz wyjścia i potokować go w coś.
Sposób, w jaki poradziłbym sobie z tym programowo, byłoby podzielenie wyniku na tablicę przez separator Space i odwołanie do niego ArrayName[2]. Jestem całkiem nowym użytkownikiem skryptów powłoki i udało mi się jedynie wykopać półkryptyczne cutprzykłady, z których żaden nie miał sensu.

Jakieś pomysły?

krystah
źródło

Odpowiedzi:

30
$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3
cucumbers

-d ' 'Mówi cutpodzielić na przestrzeniach. -f 3wybiera trzecią kolumnę.

Można również użyć awk, co robi podział w oparciu o już miejsca i sprawia, że kolumny dostępne $1, $2...

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
slhck
źródło
Zauważ, że cutnie obsłuży zmiennej liczby spacji, podczas gdy awk.
Zitrax,
13

Prawdopodobnie skorzystałbym z jednej z opcji podanych już przez @slhck, ale oto kilka innych sposobów na zrobienie tego:

  1. Używanie tablic, tak jak w każdym innym języku:

    $ foo=( $(SayStuff) ) 
    $ echo ${foo[2]}
    cucumbers

    var=()Deklaruje tablicę, $(command)zapisuje dane wyjściowe polecenia. Więc foo=( $(SayStuff) )zapisuje wyjście SayStuffdo tablicy fooi yuou wtedy echoto trzeci element z ${foo[2]}.

  2. sed

    $ SayStuff | sed 's/.* \(.*\)/\1/'
    cucumbers

    sedPolecenie zastąpić ( s///) wszystko z ostatniego słowa. Wyrażenie regularne dopasowuje wszystko do spacji ( .*), która dopasuje wszystko do ostatniej spacji, a następnie przechwytuje ostatnie słowo (\(.*\). Ponieważ słowo zostało przechwycone, możemy go nazwać jako \1.

    Prostsza wersja:

    $ SayStuff | sed 's/.* //'
    cucumbers
  3. grzmotnąć

    $ foo=$(SayStuff); echo ${foo##* } 
    cucumbers

    Wykorzystuje to zdolności manipulacji ciągiem bash, zobacz tutaj po więcej szczegółów.

  4. Więcej bashu

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
  5. Perl, gdzie oczywiście jest na to wiele sposobów:

    $ SayStuff | perl -lane 'print $F[$#F]'
    cucumber

    Te -amarki perlzachowują się jak awk, na liniach rozdzielających spacji i zapisywanie do tablicy @F. Następnie drukujemy ostatni element @F( $#Fto liczba elementów w @F). -lMówi Perl, aby dodać nową linię do każdej printdeklaracji, -nże powinien on przetwarzać STDIN linia po linii i -eże powinien uruchomić skrypt podany w wierszu poleceń.

    $ SayStuff | perl -pe 's/.* //'
    cucumber

    Opcje zostały wyjaśnione powyżej, po prostu usuwamy wszystko do ostatniej spacji i print ( -p).

    $ perl -le 'print $ARGV[$#ARGV]' $(SayStuff)
    cucumbers

    Podajemy tutaj Watermelons and cucumbersjako argumenty, które perl zapisze w @ARGtablicy, więc wypisujemy ostatni element @ARG.

  6. naciągnięcie. Ten służy seddo konwersji spacji na znaki nowej linii, a następnie taildo drukowania tylko ostatniego wiersza.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
  7. grep i wyrażenia regularne, za pomocą -októrych wypisuje tylko dopasowany ciąg.

    $ SayStuff | grep -Po '\w+$' 
    cucumbers
  8. oszukiwanie

    $ SayStuff | grep -o cucumbers
    cucumbers
terdon
źródło
2

Oto kilka wyjaśnień:

Usage: cut OPTION... [FILE]...

Print selected parts of lines from each FILE to standard output.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter

   -f, --fields=LIST
          select only these fields;  also print any line that contains  no
          delimiter character, unless the -s option is specified

Więc jeśli potrzebujesz trzeciego pola, które jest ograniczone spacjami '', to jest

$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3  
cucumbers

Jeśli chcesz pole OSTATNIE , prawdopodobnie powinieneś użyć awk .
W takim przypadku staje się:

$ echo "Arbuzy i ogórki" | awk '{print $ NF}'
ogórki

W awkNF jest liczbą pól w linii, więc $NFoznacza ostatnie pole w linii.

zeridon
źródło
w zasadzie to samo pytanie jest tutaj, ale bardziej uogólnione: stackoverflow.com/questions/3162385/... Tak, możesz użyć innych sposobów, ale awk jest najkrótszy
zeridon