Reputation: 741
How can I split a sentence using space, and print from second word onwards?
For example, if my sentence is Hello World Good Morning
, then I want to print like:
World
Good
Morning
Upvotes: 4
Views: 17703
Reputation: 4089
If you want to print on separate lines, you can use tr
:
echo "Hello World Good Morning"|tr ' ' '\n'
To start printing from the 2nd word:
echo "Hello World Good Morning"|tr ' ' '\n'|tail -n+2
Upvotes: 1
Reputation: 290075
With cut
:
$ echo "Hello World Good Morning" | cut -d' ' -f2-
World Good Morning
This tells cut
to "cut" (surprisingly) based on d
elimiter space and print from 2nd field up to the end.
With sed
:
$ echo "Hello World Good Morning" | sed 's/^[^ ]* //'
World Good Morning
This gets, from the beginning of the line (^
), a block of characters not containing a space ([^ ]*
) and then a space and replaces it with empty content. This way, the first word is deleted.
With pure bash
:
$ while IFS=" " read -r _ b; do echo "$b"; done <<< "Hello World Good Morning"
World Good Morning
This sets the field separator to the space and reads the first block in a dummy variable _
and the rest in the variable $b
. Then, it prints $b
.
Also in awk
, using this Ed Morton's approach:
$ echo 'Hello World Good Morning' | awk '{sub(/([^ ]+ +){1}/,"")}1'
World Good Morning
This replaces 1 block of not space characters
+ block of spaces
with an empty string.
Upvotes: 11
Reputation: 74685
You can change the record separator to a space in awk and print from the second record onwards:
$ awk 'NR>1' RS=' ' <<<"Hello World Good Morning"
World
Good
Morning
As pointed out in the comments, there is also an extra blank line at the end of the output. This comes from the newline at the end of the input. If you are using GNU awk, it can be suppressed by setting the record separator to the [[:space:]]
character class:
$ awk 'NR>1' RS='[[:space:]]' <<<"Hello World Good Morning"
Alternatively, as suggested by fedorqui, you can use printf
instead of echo
to pass the variable to awk:
printf '%s' 'Hello World Good Morning' | awk 'NR>1' RS=' '
Upvotes: 5
Reputation: 6239
You can use the split+glob operator:
sentence="Hello World Good Morning"
set -f # disable the glob part
IFS=" " # split on space characters:
set -- $sentence # apply the split+glob operator
# (leaving a variable expansion unquoted)
Now $1
contains Hello
... $4
contains Morning
.
shift 1 # (or just "shift") shifts the positional parameters by 1
printf '%s\n' "$@" # print them
Note that it splits on sequences of space character and ignores the leading and trailing ones.
The above works in any Bourne-like or POSIX shell except zsh
, not just bash
. With zsh
, there's no implicit split+glob operator upon variable expansion unless in sh emulation. There is an explicit split $=var
and explicit glob $~var
operator. So in zsh
:
sentence="Hello World Good Morning"
IFS=" "
set -- $=sentence
shift
printf '%s\n' "$@"
Or:
words=($=sentence)
printf '%s\n' $words[2,-1]
zsh
also has variable expansion flags including a s
one to split on a given string, and a more consistent way to nest variable expansions than in other shells, so:
$ printf '%s\n' ${${(s: :)sentence}[2,-1]}
World
Good
Morning
Upvotes: 4
Reputation: 247012
A bash-specific example:
$ read -ra words <<< "Hello World Good Morning" && printf "%s\n" "${words[@]:1}"
World
Good
Morning
Upvotes: 2
Reputation: 174786
This could be possible through grep only, if your grep supports -P
option.
grep -oP '(?:^\S+|(?<!^)\G)\h*\K\S+'
Example:
$ echo 'Hello World Good Morning' | grep -oP '(?:^\S+|(?<!^)\G)\h*\K\S+'
World
Good
Morning
$ echo 'Hello World Good' | grep -oP '(?:^\S+|(?<!^)\G)\h*\K\S+'
World
Good
$ echo 'Hello World' | grep -oP '(?:^\S+|(?<!^)\G)\h*\K\S+'
World
Upvotes: 0
Reputation: 309
$ more good
Hello World Good Morning
$ perl -p -e 's:Hello W:w:g;s: :\n:g' good
world
Good
Morning
perl -p -e # Inline edit
's:Hello W:w:g #look for Hello followed by a space and the letter W, replace it with w
;s: :\n:g' # After you replace it, find any spaces and replace with a newline
Upvotes: 0