Uvais Ibrahim
Uvais Ibrahim

Reputation: 741

Split a sentence using space in bash script

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

Answers (7)

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

fedorqui
fedorqui

Reputation: 290075

With cut:

$ echo "Hello World Good Morning" | cut -d' ' -f2-
World Good Morning

This tells cut to "cut" (surprisingly) based on delimiter 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

Tom Fenech
Tom Fenech

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

Stephane Chazelas
Stephane Chazelas

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

glenn jackman
glenn jackman

Reputation: 247012

A bash-specific example:

$ read -ra words <<< "Hello World Good Morning" && printf "%s\n" "${words[@]:1}"
World
Good
Morning

Upvotes: 2

Avinash Raj
Avinash Raj

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

munkeyoto
munkeyoto

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

Related Questions