Baris perintah: Ekstrak substring dari output

25

Katakanlah saya menjalankan perintah SayStuff

$ SayStuff

dan hasilnya

Watermelons and cucumbers

Sekarang. Katakanlah saya ingin mengekstraksi substring cucumbersdari output dan menyalurkannya ke sesuatu.
Cara saya akan melakukan ini secara terprogram adalah dengan membagi output menjadi array oleh Space pembatas dan referensi oleh ArrayName[2]. Saya cukup baru di shell script dan hanya berhasil menggali cutcontoh semi-cryptic , tidak ada yang masuk akal.

Ada ide?

krystah
sumber

Jawaban:

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

Ia -d ' 'memberitahu cutuntuk membagi pada spasi. -f 3pilih kolom ketiga.

Anda juga dapat menggunakan awk, yang melakukan pemisahan berdasarkan pada ruang sudah dan membuat kolom yang tersedia seperti $1, $2...

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
slhck
sumber
Perhatikan bahwa cuttidak akan menangani jumlah spasi variabel, saat awkdilakukan.
Zitrax
13

Saya mungkin akan menggunakan salah satu opsi yang sudah diberikan oleh @slhck tapi di sini ada beberapa cara untuk melakukan ini:

  1. Menggunakan array, seperti yang Anda lakukan dalam bahasa lain:

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

    The var=()menyatakan sebuah array, $(command)menyimpan output dari perintah. Jadi, foo=( $(SayStuff) )simpan output SayStuffke dalam array foodan kamu kemudian echoelemen ketiga ${foo[2]}.

  2. sed

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

    The sedperintah akan menggantikan ( s///) segala sesuatu dengan kata terakhir. Regex mencocokkan apa pun hingga spasi ( .*) yang akan mencocokkan semuanya hingga spasi terakhir dan kemudian menangkap kata terakhir (\(.*\). Karena kata telah ditangkap, kita dapat menyebutnya sebagai \1.

    Versi yang lebih sederhana:

    $ SayStuff | sed 's/.* //'
    cucumbers
  3. pesta

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

    Ini menggunakan kemampuan manipulasi string bash, lihat di sini untuk detail lebih lanjut.

  4. Lebih banyak bash

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
  5. Perl, di mana tentu saja, ada banyak cara untuk melakukan ini:

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

    The -amerek perlberperilaku seperti awk, garis membelah di spasi dan menyimpan ke dalam array @F. Kami kemudian mencetak elemen terakhir @F( $#Fadalah jumlah elemen dalam @F). The -lmemberitahu perl untuk menambahkan baris baru untuk setiap printpernyataan, -nbahwa ia harus memproses STDIN baris demi baris dan -ebahwa ia harus menjalankan skrip yang diberikan pada baris perintah.

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

    Opsi dijelaskan di atas, kami hanya menghapus semuanya sampai ruang terakhir dan pencetakan ( -p).

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

    Di sini kita meneruskan Watermelons and cucumberssebagai argumen, perl yang akan disimpan dalam @ARGarray dan jadi, kita mencetak elemen terakhir @ARG.

  6. tipu daya. Ini digunakan seduntuk mengkonversi spasi menjadi baris baru dan kemudian tailhanya mencetak baris terakhir.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
  7. grep dan ekspresi reguler, menggunakan -oyang hanya mencetak string yang cocok.

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

    $ SayStuff | grep -o cucumbers
    cucumbers
terdon
sumber
2

Berikut ini beberapa penjelasan:

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

Jadi jika Anda membutuhkan bidang ke-3 dan dibatasi oleh spasi '' maka itu

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

Jika Anda ingin bidang TERAKHIR Anda mungkin harus menggunakan awk .
Dalam hal ini menjadi:

$ echo "Semangka dan mentimun" |
mentimun awk '{print $ NF}'

Dalam awkNF adalah jumlah bidang dalam baris sehingga $NFberarti bidang terakhir dalam baris.

zeridon
sumber
pada dasarnya pertanyaan yang sama ada di sini tetapi lebih umum: stackoverflow.com/questions/3162385/ ... Ya Anda dapat menggunakan cara lain tetapi awk adalah yang terpendek
zeridon