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; echo3 @бунтовавшая-дома
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