Как получить первое слово вывода команды в bash?



у меня есть команда, например: echo "word1 word2". Я хочу поставить трубу (|) и получить word1 из команды.



echo "word1 word2" | ....



Я не знаю, что поставить после трубы.

913   12  

12 ответов:

Awk-хороший вариант, если вам приходится иметь дело с конечными пробелами, потому что он позаботится об этом для вас:

echo "   word1  word2 " | awk '{print ;}' # Prints "word1"

вырезать не будет заботиться об этом, хотя:

echo "  word1  word2 " | cut -f 1 -d " " # Prints nothing/whitespace

' cut ' здесь ничего не печатает / пробелы, потому что первое, что перед пробелом было другое пространство.

нет необходимости использовать внешние команды. Баш сам может сделать эту работу. Предполагая, что "word1 word2" вы получили откуда-то и хранятся в переменной, например

$ string="word1 word2"
$ set -- $string
$ echo 
word1
$ echo 
word2

теперь вы можете назначить $1 или $2 и т. д. другой переменной, если хотите.

Я думаю, что одним из эффективных способов является использование массивов bash:

array=( $string ) # do not use quotes in order to allow word expansion
echo ${array[0]}  # You can retrieve any word. Index runs from 0 to length-1

кроме того, вы можете непосредственно читать массивы в трубопроводе:

echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
echo "word1 word2 word3" | { read first rest ; echo $first ; }

Это имеет то преимущество, что не использует внешние команды и оставляет $1, $2 и т. д. переменные целы.

вы можете попробовать awk

echo "word1 word2" | awk '{ print  }'

С awk очень легко выбрать любое слово, которое вам нравится ($1, $2,...)

Если вы уверены, что нет ведущих пробелов, вы можете использовать подстановку параметров bash:

$ string="word1  word2"
$ echo ${string/%\ */}
word1

следите за выходом из одного пространства. Смотрите здесь для получения дополнительных примеров шаблонов подстановки. Если у вас есть bash > 3.0, вы также можете использовать соответствие регулярных выражений, чтобы справиться с ведущими пробелами-см. здесь:

$ string="  word1   word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
echo "word1 word2" | cut -f 1 -d " "

вырезать вырезает 1-е поле (- f 1) из списка полей, разделенных строкой ""(-d"")

read - ваш друг:

  • если строка находится в переменной:

    string="word1 word2"
    read -r first _ <<< "$string"
    printf '%s\n' "$first"
    
  • если вы работаете в трубе: первый случай: вы хотите только первое слово первой строки:

    printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
    

    второй случай: вы хотите, чтобы первое слово каждой строки:

    printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
    

они работают, если есть ведущие пробелы:

printf '%s\n' "   word1 word2" | { read -r first _; printf '%s\n' "$first"; }

я задавался вопросом, как несколько из лучших ответов измеряются с точки зрения скорости. Я проверил следующее:

1 @mattbh это!--6-->

echo "..." | awk '{print ;}'

2 @ghostdog74 это!--6-->

string="..."; set -- $string; echo 

3 @бунтовавшая-дома

echo "..." | { read -a array ; echo ${array[0]} ; }

и 4 @бунтовавшая-дома

echo "..." | { read first _ ; echo $first ; }

я измерил их с помощью timeit Python в скрипте Bash в терминале Zsh на macOS, используя тестовую строку с 215 5-буквенными словами. Делали каждое измерение пять раз (результаты были все для 100 петель, лучше всего 3) и усредняли результаты:

method       time
--------------------------------
1. awk       9.2ms
2. set       11.6ms (1.26 * "1")
3. read -a   11.7ms (1.27 * "1")
4. read      13.6ms (1.48 * "1")

хорошая работа, избиратели голоса (на момент написания этой статьи) соответствуют скорости решения!

вот еще одно решение с использованием расширение параметров оболочки. Он заботится о нескольких пробелах после первого слова. Обработка пробелов перед первым словом требует дополнительного расширения.

string='word1    word2  '
echo ${string%% *}
word1

объяснение

The %% означает удаление самого длинного матча * (пробел, за которым следует любое количество любых других символов), начиная с правой части переменной string.

поскольку perl включает в себя функциональность awk, это также можно решить с помощью perl:

echo " word1 word2" | perl -lane 'print $F[0]'

я работал со встроенным устройством, которое не имело ни perl, ни awk, ни python, а вместо этого делало это с sed. Он поддерживает несколько пробелов перед первым словом (которое cut и bash решения не справиться).

VARIABLE="  first_word_with_spaces_before_and_after  another_word  "
echo $VARIABLE | sed 's/ *\([^ ]*\).*//'

Это было очень полезно при grepping ps для идентификаторов процессов, поскольку другие решения здесь используют только bash, не смогли удалить первые пробелы, которые ps используется для выравнивания.

Comments

    Ничего не найдено.