Командная строка: извлечь подстроку из вывода

25

Скажем, я запускаю команду SayStuff

$ SayStuff

и вывод

Watermelons and cucumbers

Сейчас. Скажем, я хочу извлечь подстроку cucumbersиз вывода и передать ее во что-то.
Я бы сделал это программно, разделив выходные данные на массив по разделителю Space и сославшись на него ArrayName[2]. Я довольно плохо знаком с сценариями оболочки, и мне удалось выкопать только полукриптические cutпримеры, ни один из которых не имел смысла.

Есть идеи?

krystah
источник

Ответы:

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

-d ' 'Говорит cutразделить на пространствах. -f 3выбирает третий столбец.

Кроме того, можно использовать awk, что делает расщепление , основанное на уже пространстве и делают столбцы доступны $1, $2...

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
slhck
источник
Обратите внимание, что cutне будет обрабатывать переменное количество пробелов, а awkделать.
Цитрак
13

Я бы, вероятно, использовал один из вариантов, уже предоставленных @slhck, но вот еще несколько способов сделать это:

  1. Используя массивы, как на любом другом языке:

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

    var=()Объявляет массив, $(command)сохраняет вывод команды. Таким образом, foo=( $(SayStuff) )сохраняет вывод SayStuffв массив fooи yuou, тогда echoэто третий элемент с ${foo[2]}.

  2. sed

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

    Команда sedподставит ( s///) все с последним словом. Регулярное выражение сопоставляет что угодно, вплоть до пробела ( .*), которое будет соответствовать всему, вплоть до последнего пробела, а затем захватывает последнее слово (\(.*\). Поскольку слово было захвачено, мы можем ссылаться на него как \1.

    Более простая версия:

    $ SayStuff | sed 's/.* //'
    cucumbers
  3. удар

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

    При этом используются возможности манипуляции со строками в bash, подробности см. Здесь .

  4. Больше Баш

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
  5. Perl, где, конечно, есть много способов сделать это:

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

    В -aмарке perlведет себя как awk, расщепление линии на пробельном и сохранении в массив @F. Затем мы печатаем последний элемент @F( $#Fэто количество элементов в @F). -lГоворит Perl , чтобы добавить новую строку в каждом printзаявлении, -nчто он должен обрабатывать STDIN построчно и -eчто он должен запустить скрипт заданный в командной строке.

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

    Опции были объяснены выше, мы просто удаляем все до последнего пробела и печатаем ( -p).

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

    Здесь мы передаем в Watermelons and cucumbersкачестве аргументов, которые Perl будет сохранять в @ARGмассиве, и поэтому мы печатаем последний элемент @ARG.

  6. обман. Этот используется sedдля преобразования пробелов в новые строки, а затем tailдля печати только последней строки.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
  7. grep и регулярные выражения, с помощью -oкоторых печатается только совпадающая строка.

    $ SayStuff | grep -Po '\w+$' 
    cucumbers
  8. мошенничество

    $ SayStuff | grep -o cucumbers
    cucumbers
terdon
источник
2

Вот еще несколько объяснений:

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

Так что если вам нужно 3-е поле, и оно разделено пробелами '', то это

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

Если вы хотите поле LAST, вы, вероятно, должны использовать awk .
В этом случае это становится:

$ echo "Арбузы и огурцы" | awk '{print $ NF}'
огурцы

В awkNF - количество полей в строке, что $NFозначает последнее поле в строке.

zeridon
источник
в основном тот же вопрос здесь, но более обобщенный: stackoverflow.com/questions/3162385/… Да, вы можете использовать другие способы, но awk самый короткий
zeridon