У меня есть команда, например: echo "word1 word2"
. Я хочу поместить трубку (|
) и получить слово1 из команды.
echo "word1 word2" | ....
Я не знаю, что положить после трубы.
У меня есть команда, например: echo "word1 word2"
. Я хочу поместить трубку (|
) и получить слово1 из команды.
echo "word1 word2" | ....
Я не знаю, что положить после трубы.
Awk - хороший вариант, если вам нужно иметь дело с завершающим пробелом, потому что он позаботится об этом для вас:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Cut не позаботится об этом, хотя:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
'cut' здесь не печатает ничего/пробелы, потому что первым делом перед пробелом было другое пространство.
нет необходимости использовать внешние команды. Bash сам может выполнить эту работу. Предполагая, что слово "word1 word2" вы откуда-то получили и запомнили в переменной, например
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
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 и т.д.
Если вы уверены, что нет начальных пробелов, вы можете использовать замену параметров bash:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Следите за тем, чтобы избежать одиночного пространства. См. здесь для получения дополнительных примеров шаблонов замещения. Если у вас есть bash > 3.0, вы также можете использовать регулярное выражение для соответствия ведущим пространствам - см. здесь:
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
Вы можете попробовать awk
echo "word1 word2" | awk '{ print $1 }'
С awk очень легко выбрать любое слово, которое вам нравится ($ 1, $2,...)
Вот еще одно решение, использующее расширение параметров оболочки. Он заботится о нескольких пробелах после первого слова. Обработка пробелов перед первым словом требует одного дополнительного расширения.
string='word1 word2 '
echo ${string%% *}
word1
%%
означает удаление самого длинного совпадения *
(пробел, за которым следует любое количество любых других символов), начиная с правой стороны string
переменной.
echo "word1 word2" | cut -f 1 -d " "
cut разрезает 1-ое поле (-f 1) из списка полей, ограниченных строкой "(-d" ")
Я задавался вопросом, как некоторые из лучших ответов измеряются с точки зрения скорости. Я проверил следующее:
1 @Mattbh's
echo "..." | awk '{print $1;}'
2 @ghostdog74's
string="..."; set -- $string; echo $1
3 @boontawee-home's
echo "..." | { read -a array ; echo ${array[0]} ; }
и 4 @boontawee-home's
echo "..." | { read first _ ; echo $first ; }
Я измерял их с помощью Python timeit в скрипте 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")
Отличная работа, избиратели 👏 Голоса (на момент написания статьи) соответствуют скорости решений!
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"; }
Поскольку 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/ *\([^ ]*\).*/\1/'
Это было очень полезно при подборе ps
для идентификаторов процессов, поскольку другие решения, использующие только bash, не смогли удалить первые пробелы, которые ps
использует для выравнивания.