Ответы:
Awk - хороший вариант, если вам нужно иметь дело с конечными пробелами, потому что он позаботится об этом за вас:
echo " word1 word2 " | awk '{print $1;}' # Prints "word1"
Однако Cut об этом не позаботится:
echo " word1 word2 " | cut -f 1 -d " " # Prints nothing/whitespace
Здесь 'cut' ничего не печатает / пробел, потому что первым перед пробелом был другой пробел.
-F","чтобы переопределить разделитель полей по умолчанию (пробел) с помощью запятой.
нет необходимости использовать внешние команды. Сам Bash справится с этой задачей. Предположим, что "word1 word2" вы откуда-то взяли и сохранили в переменной, например
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
теперь вы можете присвоить $ 1 или $ 2 и т.д. другой переменной, если хотите.
stdin. @Matt M. --означает stdin, что $stringэто передается как stdin. stdinявляется разделенный пробелами в аргументы $1, $2, $3и т.д. - так же , как когда Bash Программа оценивает аргументы (например , проверка $1, $2и т.д.), этот подход имеет преимущество тенденции оболочки, чтобы расколоть stdinавтоматически в аргументы, устраняя необходимость awkили cut.
setзадает аргументы оболочки.
word1=$(IFS=" " ; set -- $string ; echo $1)Настройте IFS для правильного распознавания пробелов между словами. Заключите в круглые скобки, чтобы не повредить исходное содержимое $ 1.
string="*". Сюрприз.
Я думаю, что одним из эффективных способов является использование массивов 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 " | { read -a array ; echo ${array[0]} ; }
string="*". Сюрприз.
whileсинтаксис, чтобы получить каждое первое слово в каждой строке. В противном случае используйте подход Boontawee Home. Также обратите внимание, что echo "${array[0]}"это цитируется для предотвращения расширения, замеченного gniourf-gniourf.
echo "word1 word2 word3" | { read first rest ; echo $first ; }
Это имеет то преимущество, что не используются внешние команды и остаются неизменными переменные $ 1, $ 2 и т. Д.
$1, $2, …нетронутыми - чрезвычайно полезная функция для написания скриптов!
Если вы уверены, что в начале нет пробелов, вы можете использовать замену параметра bash:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Не упустите возможность избежать единого пространства. Дополнительные примеры шаблонов замены см. Здесь . Если у вас bash> 3.0, вы также можете использовать сопоставление регулярных выражений, чтобы справиться с ведущими пробелами - см. Здесь :
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
%% *Вот еще одно решение, использующее расширение параметра оболочки . Он заботится о нескольких пробелах после первого слова. Обработка пробелов перед первым словом требует одного дополнительного расширения.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
Знак %%означает удаление самого длинного из возможных совпадений *(пробел, за которым следует любое количество любых других символов) в конечной части string.
Мне было интересно, как можно сравнить несколько лучших ответов с точки зрения скорости. Я проверил следующее:
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 -aнедействительно в тире).
echo "word1 word2" | cut -f 1 -d " "
cut вырезает первое поле (-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"; }
Я работал со встроенным устройством, в котором не было ни Perl, ни awk, ни Python, и вместо этого делал это с помощью sed. Он поддерживает несколько пробелов перед первым словом (которое cutи bashрешения не справиться).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
Это было очень полезно при поиске psидентификаторов процессов с помощью grep, поскольку другие решения здесь, использующие только bash, не смогли удалить первые пробелы, которые psиспользуются для выравнивания.