Discussion:
[Help-bash] (no subject)
Lakshman Siddardha
2017-09-22 14:00:36 UTC
Permalink
file:list
----------------------------------------
hello
world
----------------------------------------

when i type on terminal the following command:
$ cat $file

it displays as it is in file
----------------------------------------
hello
world
----------------------------------------

when i execute a shell script, it gives output in one line only
---------------------------------------
ex.sh
----------------------------------------
lista=$(cat list)
echo $lista
-------------------------------------

it gives output of
--------------------------
hello world
-------------------------

i want new line character between "hello" and "world"
John McKown
2017-09-22 14:54:37 UTC
Permalink
On Fri, Sep 22, 2017 at 9:00 AM, Lakshman Siddardha <
Post by Lakshman Siddardha
file:list
----------------------------------------
hello
world
----------------------------------------
$ cat $file
it displays as it is in file
----------------------------------------
hello
world
----------------------------------------
when i execute a shell script, it gives output in one line only
---------------------------------------
ex.sh
----------------------------------------
lista=$(cat list)
echo $lista
-------------------------------------
it gives output of
--------------------------
hello world
-------------------------
i want new line character between "hello" and "world"
​This is "working as designed". Why? Well when the "cat list" is executed,
the output, as you know, is: hello\nworld\n (where \n is the C escape
representing the <newline> character). Now, the key to this entire thing is
understanding how BASH interprets this character string. BASH, by default,
splits the the command line according to the characters in the IFS
environment variable, if set. If IFS is not set, then BASH splits the
command line at every <tab>, <space>, or <newline>. So the the <newline> is
treated the same as a <space>, and you end up with two parameters (hello)
and (world) which are concatenated back together with a separating <space>.
It's just how BASH works. Now, after all that, which I recognize is likely
not really a very good explanation, what you can do IN THIS CASE, is to
"temporarily" set the IFS environment variable to "nothing" just for the
assignment. That is, do:

IFS="" lista=$(cat list)
echo $lista
--
*L'Shanah Tovah Tikatevu*

Maranatha! <><
John McKown
Greg Wooledge
2017-09-22 15:03:12 UTC
Permalink
Post by John McKown
IFS="" lista=$(cat list)
echo $lista
This is also wrong. You MUST QUOTE the variable expansion on line 2.
That's all. Nothing you do on line 1 matters.
John McKown
2017-09-22 15:33:00 UTC
Permalink
Post by Greg Wooledge
Post by John McKown
IFS="" lista=$(cat list)
echo $lista
This is also wrong. You MUST QUOTE the variable expansion on line 2.
That's all. Nothing you do on line 1 matters.
​I will agree that your method is superior. However, mine does work. At
least on my Linux system (Fedora 25)

$ IFS="" lista=$(cat list)
$ echo $lista
hello
world

Your solution, as I understand it:

$ lista=$(cat list)
$ echo "$lista"
hello
world

Yet another solution:

$ lista="$(cat list)"
$ echo $lista
hello
world


All of the above are the cut'n'paste from my Linux/Intel system, Linux
it-johnmckown-linux 4.11.12-200.fc25.x86_64 #1 SMP Fri Jul 21 16:41:43 UTC
2017 x86_64 x86_64 x86_64 GNU/Linux
using bash 4.3.43(1)-release
--
*L'Shanah Tovah Tikatevu*

Maranatha! <><
John McKown
Chet Ramey
2017-09-22 15:35:31 UTC
Permalink
Post by John McKown
​I will agree that your method is superior. However, mine does work. At
least on my Linux system (Fedora 25)
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
This leaves IFS set to the empty string, which might lead to unexpected
results for subsequent commands.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://cnswww.cns.cwru.edu/~chet/
John McKown
2017-09-22 15:43:43 UTC
Permalink
Post by Chet Ramey
Post by John McKown
​I will agree that your method is superior. However, mine does work. At
least on my Linux system (Fedora 25)
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
This leaves IFS set to the empty string, which might lead to unexpected
results for subsequent commands.
​My bad. I overlooked that. I was thinking that since I didn't do an
"export IFS", that the variable only retained its value during the
execution of that one line. On my system, I see:

$ echo -n $IFS|od -tcx1
0000000
$ IFS="-" : do nothing
$ echo -n $IFS|od -tcx1
0000000
$

Post by Chet Ramey
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
chet/
--
*L'Shanah Tovah Tikatevu*

Maranatha! <><
John McKown
Chet Ramey
2017-09-22 15:47:57 UTC
Permalink
Post by Chet Ramey
Post by John McKown
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
This leaves IFS set to the empty string, which might lead to unexpected
results for subsequent commands.
​My bad. I overlooked that. I was thinking that since I didn't do an
"export IFS", that the variable only retained its value during the
execution of that one line.
It's an assignment statement like any other, and there are no commands
other than assignment statements on that line, so all the assignments
affect the current shell.
Post by Chet Ramey
$ IFS="-" : do nothing
$ echo -n $IFS|od -tcx1
0000000
the assignment only lasts for the duration of the command (posix
alters those semantics somewhat).
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://cnswww.cns.cwru.edu/~chet/
John McKown
2017-09-22 15:54:53 UTC
Permalink
Post by Chet Ramey
Post by Chet Ramey
Post by John McKown
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
This leaves IFS set to the empty string, which might lead to
unexpected
Post by Chet Ramey
results for subsequent commands.
​My bad. I overlooked that. I was thinking that since I didn't do an
"export IFS", that the variable only retained its value during the
execution of that one line.
It's an assignment statement like any other, and there are no commands
other than assignment statements on that line, so all the assignments
affect the current shell.
Post by Chet Ramey
$ IFS="-" : do nothing
$ echo -n $IFS|od -tcx1
0000000
the assignment only lasts for the duration of the command (posix
alters those semantics somewhat).
​Many thanks. I've learned quite a bit that I guess was for "experts",
which I am not.​
Post by Chet Ramey
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
chet/
--
*L'Shanah Tovah Tikatevu*

Maranatha! <><
John McKown
Greg Wooledge
2017-09-22 16:12:36 UTC
Permalink
Post by John McKown
$ echo -n $IFS|od -tcx1
0000000
This does not show the value of IFS correctly because, again, you have
failed to quote properly.

wooledg:~$ IFS=$' \t\n' # default value of IFS
wooledg:~$ echo -n $IFS | od -tcx1
0000000
wooledg:~$ printf %s "$IFS" | od -tcx1
0000000 \t \n
20 09 0a
0000003

http://mywiki.wooledge.org/Quotes
DJ Mills
2017-09-22 16:14:03 UTC
Permalink
Post by John McKown
My bad. I overlooked that. I was thinking that since I didn't do an
"export IFS", that the variable only retained its value during the
$ echo -n $IFS|od -tcx1
0000000
$ IFS="-" : do nothing
$ echo -n $IFS|od -tcx1
0000000
$
It's different because in your example you're not actually running a
command, you're just doing two variable assignments (the command
substitution doesn't count).

Also setting IFS like that for a command won't affect the wordsplitting for
that command itself, just export the IFS value to the subprocess's
environment.

Regardless, it's a horrid, hacky way of doing it. Just quote your
expansions and be done with it

Greg Wooledge
2017-09-22 15:40:57 UTC
Permalink
Post by John McKown
​I will agree that your method is superior. However, mine does work. At
least on my Linux system (Fedora 25)
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
Wronger and wronger.

wooledg:~$ printf '*\n' > list
wooledg:~$ IFS="" lista=$(cat list)
wooledg:~$ echo $lista
[ { 0.1 0400_0001.pdf 1 11412687.html 11412687.pdf 11412859.html 11412859.pdf 11412879.html 11412879-mod.html 11412879-mod.pdf 11412879.pdf 11412939.html 11412939.pdf 11421107.html 11421107.pdf 11423576.pdf 12.bash 1429_001.pdf .....

http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/BashPitfalls#pf14

Looks like I have a few junk files I can rm.
John McKown
2017-09-22 15:53:46 UTC
Permalink
Post by Greg Wooledge
Post by John McKown
​I will agree that your method is superior. However, mine does work. At
least on my Linux system (Fedora 25)
$ IFS="" lista=$(cat list)
$ echo $lista
hello
world
Wronger and wronger.
wooledg:~$ printf '*\n' > list
wooledg:~$ IFS="" lista=$(cat list)
wooledg:~$ echo $lista
[ { 0.1 0400_0001.pdf 1 11412687.html 11412687.pdf 11412859.html
11412859.pdf 11412879.html 11412879-mod.html 11412879-mod.pdf 11412879.pdf
11412939.html 11412939.pdf 11421107.html 11421107.pdf 11423576.pdf 12.bash
1429_001.pdf .....
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/BashPitfalls#pf14
Looks like I have a few junk files I can rm.
​​
​I concede your point. I had not considered shell file globbing, just
"regular" characters.​
--
*L'Shanah Tovah Tikatevu*

Maranatha! <><
John McKown
Loading...