I have a command, for example: echo "word1 word2"
. I want to put a pipe (|
) and get word1 from the command.
echo "word1 word2" | ....
I don't know what to put after the pipe.
This question is related to
bash
echo "word1 word2" | cut -f 1 -d " "
cut cuts the 1st field (-f 1) from a list of fields delimited by the string " " (-d " ")
As perl incorporates awk's functionality this can be solved with perl too:
echo " word1 word2" | perl -lane 'print $F[0]'
I think one efficient way is the use of bash arrays:
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
Also, you can directly read arrays in a pipe-line:
echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done
I was working with a embedded device which had neither perl, awk or python and did it with sed instead. It supports multiple spaces before the first word (which the cut
and bash
solutions did not handle).
VARIABLE=" first_word_with_spaces_before_and_after another_word "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'
This was very useful when grepping ps
for process IDs since the other solutions here using only bash was not able to remove the first spaces which ps
uses to align.
read
is your friend:
If string is in a variable:
string="word1 word2"
read -r first _ <<< "$string"
printf '%s\n' "$first"
If you're working in a pipe: first case: you only want the first word of the first line:
printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }
second case: you want the first word of each line:
printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done
These work if there are leading spaces:
printf '%s\n' " word1 word2" | { read -r first _; printf '%s\n' "$first"; }
You could try awk
echo "word1 word2" | awk '{ print $1 }'
With awk it is really easy to pick any word you like ($1, $2, ...)
echo "word1 word2 word3" | { read first rest ; echo $first ; }
This has the advantage that is not using external commands and leaves the $1, $2, etc. variables intact.
%% *
Here is another solution using shell parameter expansion. It takes care of multiple spaces after the first word. Handling spaces in front of the first word requires one additional expansion.
string='word1 word2'
echo ${string%% *}
word1
string='word1 word2 '
echo ${string%% *}
word1
The %%
signifies deleting the longest possible match of *
(a space followed by any number of whatever other characters) in the trailing part of string
.
I wondered how several of the top answers measured up in terms of speed. I tested the following:
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]} ; }
and 4 @boontawee-home's
echo "..." | { read first _ ; echo $first ; }
I measured them with Python's timeit in a Bash script in a Zsh terminal on macOS, using a test string with 215 5-letter words. Did each measurement five times (the results were all for 100 loops, best of 3), and averaged the results:
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")
Nice job, voters The votes (as of this writing) match the solutions' speed!
If you are sure there are no leading spaces, you can use bash parameter substitution:
$ string="word1 word2"
$ echo ${string/%\ */}
word1
Watch out for escaping the single space. See here for more examples of substitution patterns. If you have bash > 3.0, you could also use regular expression matching to cope with leading spaces - see here:
$ string=" word1 word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1
no need to use external commands. Bash itself can do the job. Assuming "word1 word2" you got from somewhere and stored in a variable, eg
$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2
now you can assign $1, or $2 etc to another variable if you like.
Source: Stackoverflow.com