AWK FS with ignore space option

Hi,
i have in a situation to get the variables which are having a "|" delimiter and each variable may or may not have spaces, so how can i skip the spaces on the string and print the string as it is.

For example:
line = "|Hello world|Hello|Hi Guys|
read x y z <<<$(echo "$line" | awk -F"|" '{print $1,$2,$3}')
echo -e "$x" (should be 'Hello world')

buts it's printing only Hello.

Could some one please help me.

No awk needed, try this:

line = "|Hello world|Hello|Hi Guys|"

OLDIFS="$IFS"
IFS="|"
set -- $line
IFS="$OLDIFS"

echo "$2"
echo "$3"
echo "$4"

Or this, since you have BASH:

IFS="|" read A B C D E <<<"|a b|c d|e f|g h"

Thanks a lot, it's woks perfectly, can you please explain about the following code.

OLDIFS="$IFS"
IFS="|"
set -- $line
IFS="$OLDIFS"

Since you don't have a closing double-quote at the end of the 1st line of this script, I'm VERY surprised that you didn't get a syntax error.

What corona688 suggested should get you what you want. But, assuming you had supplied the closing double quote, let's evaluate what is going on so you may understand why you would get "Hello" assigned to x instead of "Hello World". So, assuming we start with the script:

line = "|Hello world|Hello|Hi Guys|"
read x y z <<<$(echo "$line" | awk -F"|" '{print $1,$2,$3}')
echo -e "$x" (should be 'Hello world')

then the output from

echo "$line" | awk -F"|" '{print $1,$2,$3}'

on line2 will be the string " Hello World Hello\n" because with your input field separator set to "|" in awk, $1 will be set to an empty string (what appeared in $line before the 1st "|"), $2 will be set to "Hello World", and $3 will be set to "Hello". The awk print command adds an output field separator (in this case a space) between the expansion of $1 and $2, another separator between the expansion of $2 and $3, and adds a newline terminator after the expansion of $3.

So after we're done with awk, line2 in the script is essentially:

echo " Hello World Hello"|read x y z

(ignoring the fact that the read could be executed in a subshell on some systems). Now, since you haven't given us any indication that you've changed the setting of IFS we'll assume that it the default string containing a space, a tab, and a new-line character. So read will split the line it reads and set x to Hello, y to World, and z to the remainder of the line up to the terminating new-line (which in this case is the final Hello).

So line 3 in your script echo $x (the -e option makes no difference since you know in this script that the string passed to echo can't contain any backslash escape sequences) prints "Hello" and adds a line terminating new-line character.

IFS is the shell's input field separator character list. Note that in the last post by corona688, he set IFS to "|", but only for the read command. If the command he gave had been:

IFS="|" ; read A B C D E <<<"|a b|c d|e f|g h"

instead of

IFS="|" read A B C D E <<<"|a b|c d|e f|g h"

the setting of IFS would have applied to the rest of the line parsing performed by this shell instead of just the line parsin performed by the read.

The command sequence:

OLDIFS="$IFS"
IFS="|"
...
IFS="$OLDIFS"

saves the current value of IFS in OLDIFS, sets IFS to the vertical-bar
runs whatever is specified by ... and then restores the original value of IFS.

The set -- $line sets the shell's positional parameters ($1, $2, ... $n) and $# by splitting the value stored in the line variable using the current field separator ("|").

IFS is a special variable which controls string splitting in shell. Ordinarily it splits on spaces, but it can split on other things as well. So:

1) Save default value of IFS for later.
2) Set IFS to |
3) Set the $1 $2 $3 $4 variables to $line, splitting on |
4) Restore IFS to its original value

You can also use IFS in concert with READ, like

IFS="|" read A B C D where read will split upon |, not whitespace. Because IFS is prefixed to that line, IFS will be changed only for that line and does not need to be restored. This doesn't work for set for some reason.