[opensuse] BASH - howto 'read' line in file and preserve leading whitespace?
Listmates, I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line making the subsequent write impossible. I was using a while loop as follows: { while read XTAG VALUE LINE; do if [[ ${XTAG} == "X-Mozilla-Status:" ]]; then case ${VALUE} in 1019 ) NEWVAL=1011;; 1009 ) NEWVAL=1001;; 001b ) NEWVAL=0013;; 0019 ) NEWVAL=0011;; 000b ) NEWVAL=0003;; 0009 ) NEWVAL=0001;; * ) NEWVAL=${VALUE};; esac echo -e "${XTAG} ${NEWVAL} ${LINE}" >> ${NEWFILE} else echo -e "${XTAG} ${VALUE} ${LINE}" >> ${NEWFILE} fi XTAG=''; VALUE=''; LINE=''; NEWVAL='' done } < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav All of the lines in the mailbox with leading whitespace were written without the leading whitespace like: original file: Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net newfile: Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net Is there a bash trick that will preserve the whitespace? -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
David C. Rankin wrote:
Listmates,
I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line
Hi David yes, that is exactly what read is intended to do.
I was using a while loop as follows:
[snip] So, you'd like to read the file line-by-line, do some tests on it, and write it back out, possibly modified?
Is there a bash trick that will preserve the whitespace?
How about sed ? /Per Jessen, Zürich -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
Try REXX: (I used REXX for various things for over 20 years (Linux, Windows & Mainframe) Download Regina REXX http://regina-rexx.sourceforge.net/ convert.cmd = REXX program NameAddress.txt = input file converted.txt = output file -- Duaine Hechler Piano, Player Piano, Pump Organ Tuning, Servicing & Rebuilding Associate Member of the Piano Technicians Guild Reed Organ Society Member St. Louis, MO 63034 (314) 838-5587 dahechler@charter.net www.hechlerpianoandorgan.com -- Home & Business user of Linux - 9+ years #!/usr/bin/rexx /* */ DO FOREVER recin = LINEIN('NameAddress.txt') IF recin = "" THEN EXIT /* ***** convert all to upper case ***** */ UPPER recin /* ***** breakdown by fields ***** */ name = SUBSTR(recin,1,20) address = SUBSTR(recin,21,20) city = SUBSTR(recin,41,20) state = SUBSTR(recin,61,10) zip = SUBSTR(recin,71,20) /* ***** convert name to last name, first name ***** */ name = word(name,2)||", "||word(name,1) /* ***** convert city state zip to mailing format ***** */ csz = word(city,1)||", "||word(state,1)||" "||word(zip,1) /* ***** build output record ***** */ recout = "" recout = OVERLAY(name,recout,1,20) recout = OVERLAY(address,recout,21,20) recout = OVERLAY(csz,recout,41,40) call LINEOUT 'converted.txt', recout END /* DO */ EXIT HECHLER, DUAINE 1013 JUSTICE CT. FLORISSANT, MO 63034 HECHLER, KEVIN 1023 JUSTICE CT. HAZELWOOD, MO 63034 CRUISE, TOM 1033 JUSTICE CT. DELLWOOD, MO 63034 Duaine Hechler 1013 Justice Ct. Florissant MO 63034 Kevin Hechler 1023 Justice Ct. Hazelwood MO 63034 Tom Cruise 1033 Justice Ct. Dellwood MO 63034
Try REXX: (I used REXX for various things for over 20 years (Linux, Windows & Mainframe) Download Regina REXX http://regina-rexx.sourceforge.net/ convert.rexx = REXX program NameAddress.txt = input file converted.txt = output file -- Duaine Hechler Piano, Player Piano, Pump Organ Tuning, Servicing & Rebuilding Associate Member of the Piano Technicians Guild Reed Organ Society Member St. Louis, MO 63034 (314) 838-5587 dahechler@charter.net www.hechlerpianoandorgan.com -- Home & Business user of Linux - 9+ years HECHLER, DUAINE 1013 JUSTICE CT. FLORISSANT, MO 63034 HECHLER, KEVIN 1023 JUSTICE CT. HAZELWOOD, MO 63034 CRUISE, TOM 1033 JUSTICE CT. DELLWOOD, MO 63034 Duaine Hechler 1013 Justice Ct. Florissant MO 63034 Kevin Hechler 1023 Justice Ct. Hazelwood MO 63034 Tom Cruise 1033 Justice Ct. Dellwood MO 63034 #!/usr/bin/rexx /* */ DO FOREVER recin = LINEIN('NameAddress.txt') IF recin = "" THEN EXIT /* ***** convert all to upper case ***** */ UPPER recin /* ***** breakdown by fields ***** */ name = SUBSTR(recin,1,20) address = SUBSTR(recin,21,20) city = SUBSTR(recin,41,20) state = SUBSTR(recin,61,10) zip = SUBSTR(recin,71,20) /* ***** convert name to last name, first name ***** */ name = word(name,2)||", "||word(name,1) /* ***** convert city state zip to mailing format ***** */ csz = word(city,1)||", "||word(state,1)||" "||word(zip,1) /* ***** build output record ***** */ recout = "" recout = OVERLAY(name,recout,1,20) recout = OVERLAY(address,recout,21,20) recout = OVERLAY(csz,recout,41,40) call LINEOUT 'converted.txt', recout END /* DO */ EXIT
Try REXX: (I've used REXX for various things for over 20 years (Linux, Windows & Mainframe) Download Regina REXX http://regina-rexx.sourceforge.net/ Sample program and files: #!/usr/bin/rexx /* */ DO FOREVER recin = LINEIN('NameAddress.txt') IF recin = "" THEN EXIT /* ***** convert all to upper case ***** */ UPPER recin /* ***** breakdown by fields ***** */ name = SUBSTR(recin,1,20) address = SUBSTR(recin,21,20) city = SUBSTR(recin,41,20) state = SUBSTR(recin,61,10) zip = SUBSTR(recin,71,20) /* ***** convert name to last name, first name ***** */ name = word(name,2)||", "||word(name,1) /* ***** convert city state zip to mailing format ***** */ csz = word(city,1)||", "||word(state,1)||" "||word(zip,1) /* ***** build output record ***** */ recout = "" recout = OVERLAY(name,recout,1,20) recout = OVERLAY(address,recout,21,20) recout = OVERLAY(csz,recout,41,40) call LINEOUT 'converted.txt', recout END /* DO */ EXIT ----- input file ----- Duaine Hechler 1013 Justice Ct. Florissant MO 63034 Kevin Hechler 1023 Justice Ct. Hazelwood MO 63034 Tom Cruise 1033 Justice Ct. Dellwood MO 63034 ----- output file ----- HECHLER, DUAINE 1013 JUSTICE CT. FLORISSANT, MO 63034 HECHLER, KEVIN 1023 JUSTICE CT. HAZELWOOD, MO 63034 CRUISE, TOM 1033 JUSTICE CT. DELLWOOD, MO 63034 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thu, Sep 04, 2008 at 01:10:16AM -0500, David C. Rankin wrote:
Listmates,
I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line making the subsequent write impossible. I was using a while loop as follows:
{ while read XTAG VALUE LINE; do if [[ ${XTAG} == "X-Mozilla-Status:" ]]; then case ${VALUE} in 1019 ) NEWVAL=1011;; 1009 ) NEWVAL=1001;; 001b ) NEWVAL=0013;; 0019 ) NEWVAL=0011;; 000b ) NEWVAL=0003;; 0009 ) NEWVAL=0001;; * ) NEWVAL=${VALUE};; esac echo -e "${XTAG} ${NEWVAL} ${LINE}" >> ${NEWFILE} else echo -e "${XTAG} ${VALUE} ${LINE}" >> ${NEWFILE} fi XTAG=''; VALUE=''; LINE=''; NEWVAL='' done } < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav
All of the lines in the mailbox with leading whitespace were written without the leading whitespace like:
original file:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
newfile:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
Just use the IFS variable. while IFS=$'\n' read line ; do if [[ $line =~ ^X-Mozilla-Status: ]] ; then value=${line#*:} value=${value%%[[:blank:]]*} case $value in 1019 ) line=${line/1019/1011} ;; 1009 ) line=${line/1009/1001} ;; 001b ) line=${line/001b/0013} ;; 0019 ) line=${line/0019/0011} ;; 000b ) line=${line/000b/0003} ;; 0009 ) line=${line/0009/0001} ;; esac fi echo "$line" >> ${NEWFILE} done < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav but this could also be done with sed. Btw: To make sed to use POSIX.2 regular expressions simply use the option -r as the first option of sed and you're fine. sed -r -e '/^X-Mozilla-Status:/{ s/1019/1011/ s/1009/1001/ s/001b/0013/ s/0019/0011/ s/000b/0003/ s/0009/0001/ }' < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav > ${NEWFILE} Werner -- "Having a smoking section in a restaurant is like having a peeing section in a swimming pool." -- Edward Burr -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
Dr. Werner Fink wrote:
On Thu, Sep 04, 2008 at 01:10:16AM -0500, David C. Rankin wrote:
Listmates,
I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line making the subsequent write impossible. I was using a while loop as follows:
{ while read XTAG VALUE LINE; do if [[ ${XTAG} == "X-Mozilla-Status:" ]]; then case ${VALUE} in <snip>
All of the lines in the mailbox with leading whitespace were written without the leading whitespace like:
Just use the IFS variable.
while IFS=$'\n' read line ; do if [[ $line =~ ^X-Mozilla-Status: ]] ; then value=${line#*:} value=${value%%[[:blank:]]*} case $value in 1019 ) line=${line/1019/1011} ;; 1009 ) line=${line/1009/1001} ;; 001b ) line=${line/001b/0013} ;; 0019 ) line=${line/0019/0011} ;; 000b ) line=${line/000b/0003} ;; 0009 ) line=${line/0009/0001} ;; esac fi echo "$line" >> ${NEWFILE} done < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav
<snip>
Werner
Thank you Dr. Fink, Patrick, Brian and Per, This is exactly what I was trying to do. I had been over the Parameter Expansion section of man bash several times, but could not figure out how to put the pieces of the puzzle together. This hit the nail on the head. The sed example was something I had looked at but decided against due to the overhead of repeated sed calls ( 3,869,388 times adds up ). The IFS environment discussion was also good learning as I routinely used OLDIFS to hold and reset the IFS variable, many times when it wasn't needed. Thanks again! -- David C. Rankin, J.D.,P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
Dr. Werner Fink wrote:
On Thu, Sep 04, 2008 at 01:10:16AM -0500, David C. Rankin wrote:
Listmates,
I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line making the subsequent write impossible. I was using a while loop as follows:
{ while read XTAG VALUE LINE; do if [[ ${XTAG} == "X-Mozilla-Status:" ]]; then case ${VALUE} in 1019 ) NEWVAL=1011;; 1009 ) NEWVAL=1001;; 001b ) NEWVAL=0013;; 0019 ) NEWVAL=0011;; 000b ) NEWVAL=0003;; 0009 ) NEWVAL=0001;; * ) NEWVAL=${VALUE};; esac echo -e "${XTAG} ${NEWVAL} ${LINE}" >> ${NEWFILE} else echo -e "${XTAG} ${VALUE} ${LINE}" >> ${NEWFILE} fi XTAG=''; VALUE=''; LINE=''; NEWVAL='' done } < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav
All of the lines in the mailbox with leading whitespace were written without the leading whitespace like:
original file:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
newfile:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
Just use the IFS variable.
while IFS=$'\n' read line ; do if [[ $line =~ ^X-Mozilla-Status: ]] ; then value=${line#*:} value=${value%%[[:blank:]]*} case $value in 1019 ) line=${line/1019/1011} ;; 1009 ) line=${line/1009/1001} ;; 001b ) line=${line/001b/0013} ;; 0019 ) line=${line/0019/0011} ;; 000b ) line=${line/000b/0003} ;; 0009 ) line=${line/0009/0001} ;; esac fi echo "$line" >> ${NEWFILE} done < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav
Werner, I have a question. Is the value=${value%%[[:blank:]]*} right? It looks like it is deleting everything in the parameter $value. Testing yields: if [[ $line =~ ^X-Mozilla-Status: ]] ; then echo -e "line = $line" value=${line#*:} echo -e "\tvalue=\${line#*:} = '$value'" value=${value%%[[:blank:]]*} echo -e "\t\${value%%[[:blank:]]*} = '$value'\n" line = X-Mozilla-Status: 0009 value=${line#*:} = ' 0009' ${value%%[[:blank:]]*} = '' Shouldn't it be value=${value##[[:blank:]]} ? Doing this way yields the intended result: line = X-Mozilla-Status: 0009 value=${line#*:} = ' 0009' ${value%%[[:blank:]]*} = '0009' Also, couldn't we eliminate the second value expression altogether by including the [[:blank:]] in the first value expression like this: value=${line#*:[[:blank:]]} which yields: line = X-Mozilla-Status: 0009 value=${line#*:[[:blank:]]} = '0009' Are there some gotchas in there? Just curious. Perhaps it was just slyly meant for additional learning.... -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thu, Sep 04, 2008 at 02:01:53PM -0500, David C. Rankin wrote:
Werner,
I have a question. Is the value=${value%%[[:blank:]]*} right? It looks like it is deleting everything in the parameter $value.
... normally the `*' in bash means not `match a sequence of 0 or more of the atom' but simply `Matches any string, including the null string'. Nevertheless bash 3.2.x understands the regular expression `[[:blank:]]' which is a space or a tab.
Testing yields:
if [[ $line =~ ^X-Mozilla-Status: ]] ; then echo -e "line = $line" value=${line#*:} echo -e "\tvalue=\${line#*:} = '$value'" value=${value%%[[:blank:]]*} echo -e "\t\${value%%[[:blank:]]*} = '$value'\n"
line = X-Mozilla-Status: 0009 value=${line#*:} = ' 0009' ${value%%[[:blank:]]*} = ''
Yes your're right the patterb matches all blanks followed by a string.
Shouldn't it be value=${value##[[:blank:]]} ? Doing this way yields the intended result:
line = X-Mozilla-Status: 0009 value=${line#*:} = ' 0009' ${value%%[[:blank:]]*} = '0009'
Also, couldn't we eliminate the second value expression altogether by including the [[:blank:]] in the first value expression like this:
value=${line#*:[[:blank:]]} which yields:
line = X-Mozilla-Status: 0009 value=${line#*:[[:blank:]]} = '0009'
Are there some gotchas in there? Just curious. Perhaps it was just slyly meant for additional learning....
learning means just doit ;) Werner -- "Having a smoking section in a restaurant is like having a peeing section in a swimming pool." -- Edward Burr -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
----- Original Message ----- From: "David C. Rankin" <drankinatty@suddenlinkmail.com> To: "suse" <opensuse@opensuse.org> Sent: Thursday, September 04, 2008 2:10 AM Subject: [opensuse] BASH - howto 'read' line in file and preserve leading whitespace?
Listmates,
I stumbled on a problem trying to read a file (email mailbox) line-by-line in bash. Using the built-in read, it strips the leading whitespace from each line making the subsequent write impossible. I was using a while loop as follows:
{ while read XTAG VALUE LINE; do if [[ ${XTAG} == "X-Mozilla-Status:" ]]; then case ${VALUE} in 1019 ) NEWVAL=1011;; 1009 ) NEWVAL=1001;; 001b ) NEWVAL=0013;; 0019 ) NEWVAL=0011;; 000b ) NEWVAL=0003;; 0009 ) NEWVAL=0001;; * ) NEWVAL=${VALUE};; esac echo -e "${XTAG} ${NEWVAL} ${LINE}" >> ${NEWFILE} else echo -e "${XTAG} ${VALUE} ${LINE}" >> ${NEWFILE} fi XTAG=''; VALUE=''; LINE=''; NEWVAL='' done } < ~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav
All of the lines in the mailbox with leading whitespace were written without the leading whitespace like:
original file:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
newfile:
Received: from edge03.suddenlink.net ([195.135.221.135]) by imta03.suddenlink.net
Is there a bash trick that will preserve the whitespace?
Try this: --- INFILE="~/.thunderbird/2k12pnl0.default/Mail/pop.suddenlinkmail.com/openSuSE.sav" OUTFILE="some_file" DONE=false until $DONE ; do IFS="" read || DONE=true [[ "${REPLY%%:*}" == "X-Mozilla-Status" ]] || echo "$REPLY" ; continue VAL=${REPLY#*:} VAL=${VAL// /} case "$VAL" in 1019) VAL=1011 ;; 1009) VAL=1001 ;; 001b) VAL=0013 ;; 0019) VAL=0011 ;; 000b) VAL=0003 ;; 0009) VAL=0001 ;; esac echo "${REPLY%%:*}: $VAL" done <$INFILE >$OUTFILE --- explaination: IFS="" Eliminate any word seperator so read sees the whole line as one big word, including the leading, trailing, and all other spaces. Line break still breaks on linefeed and the ifs change only effects the read command, nothing else in the script. read (with no variable) just my minimalist nature. we happen to only need one variable, and read happens to supply a variable REPLY if no other specified. ${REPLY%%:*} display part of $REPLY , from beginning to the first ":" , non-inclusive. For sanity sake, you should always try to compare things in the same context. so, either quote, or don't quote the values on both sides of the test comparator If you have to quote one side for any reason, then quote the other side too. Most times when either side is a variable then you should quote, to account for the possibility of the variable being empty. If that doesn't match, then echo the entire line verbatim and skip the rest of the loop. I re-arranged the loop that way because 99% of lines will not match, so this way 99% of the time we do almost no work. Also, this way we are almost impervious to the content of the line. We don't care what's in it or have to parse all the possible types of lines and reconstruct them, we just spit the whole line back out without even looking at it. The rest only ever happens on those rare lines when we didn't skip out above, VAL=${REPLY#*:} VAL=everything from the 1st colon to end of line case "${VAL// /}" in VAL with all spaces stripped out. I'm assuming that on THESE particular lines that this is reasonable. IE that these lines have the format "tag: value" with no other junk after the colon. So that taking everything after the colon, and then stripping all spaces anywhere, will leave you with a clean "####" for case-matching. If there is any other stuff, well no problem, since these are mail headers and they have an intentionally regular, defined, parseable structure. So if we need to do another split on a comma or a semicolon or something, it's just another VAL=${VAL%%,*} or some such. theres really no need for val & newval, just start with val, and sometimes overwrite it. echo "${REPLY%%:*}: $VAL" Whether we changed VAL or not, either way we simply (re)create the line out of the parts the same way every time. We word-split on the : so we have to put one back in ourselves. Finally, if the input file happens to end at the end of the last line (ie, no final linefeed), then that last line will not be processed and will NOT appear in the output, because the "while read" will exit with an exit status above 0 on hitting the end of file, and so the rest of the loop will not get a chance to run that one last time. To allow for that possibility you need to put the read within a different loop that exits on a variable instead of directly on the exit status of read itself. Then in the loop merely remember the exit status of read but proceed to do that iteration of the loop. So, this: while IFS="" read ;do [...] done <infile >outfile Becomes this: DONE=false until $DONE ;do IFS="" read || DONE=true [...] done <infile >outfile Brian K. White brian@aljex.com http://www.myspace.com/KEYofR +++++[>+++[>+++++>+++++++<<-]<-]>>+.>.+++++.+++++++.-.[>+<---]>++. filePro BBx Linux SCO FreeBSD #callahans Satriani Filk! -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
* Brian K. White <brian@aljex.com> [09-04-08 06:35]:
Becomes this:
DONE=false until $DONE ;do IFS="" read || DONE=true [...] done <infile >outfile
Shouldn't you clean-up after yourself and reset the $IFS to it's expected value? -- Patrick Shanahan Plainfield, Indiana, USA HOG # US1244711 http://wahoo.no-ip.org Photo Album: http://wahoo.no-ip.org/gallery2 Registered Linux User #207535 @ http://counter.li.org -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thu, Sep 4, 2008 at 7:47 AM, Patrick Shanahan <paka@opensuse.org> wrote:
* Brian K. White <brian@aljex.com> [09-04-08 06:35]:
Becomes this:
DONE=false until $DONE ;do IFS="" read || DONE=true [...] done <infile >outfile
Shouldn't you clean-up after yourself and reset the $IFS to it's expected value?
I don't normally bother. When the batch script ends, all the local variables will go away anyway. FYI: Not true if the script is invoked via the '.' operator. ie. . <path/to/script> Greg -- Greg Freemyer Litigation Triage Solutions Specialist http://www.linkedin.com/in/gregfreemyer First 99 Days Litigation White Paper - http://www.norcrossgroup.com/forms/whitepapers/99%20Days%20whitepaper.pdf The Norcross Group The Intersection of Evidence & Technology http://www.norcrossgroup.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
----- Original Message ----- From: "Patrick Shanahan" <paka@opensuse.org> To: <opensuse@opensuse.org> Sent: Thursday, September 04, 2008 7:47 AM Subject: Re: [opensuse] BASH - howto 'read' line in file and preserve leading whitespace?
* Brian K. White <brian@aljex.com> [09-04-08 06:35]:
Becomes this:
DONE=false until $DONE ;do IFS="" read || DONE=true [...] done <infile >outfile
Shouldn't you clean-up after yourself and reset the $IFS to it's expected value?
Nope. There is nothing to clean up. IFS has not been changed. When a variable is set in this manner, on the same line as, and preceding, a command, it only affects the environment of the command, not the current environment. Try this: FOO=yes FOO=no eval 'echo $FOO' echo $FOO FOO=yes affects the current environment FOO=no affects only the environment of "eval..." You need this eval syntax as a way to enclose $FOO in single-quotes to keep the current shell from expanding $FOO itself before handing it to echo. If you say for instance: FOO=yes FOO=no echo $FOO It will say "yes" , which may confuse the heck out of you. What happens in that case is, the current environment has FOO=yes Then we set FOO=no in echo's environment, but we never see that because "echo $VARIABLE" does not resolve VARIABLE out of echo's own environment. echo just echos things from it's command line. echo's command line was assembled by our current shell, which expanded $FOO from IT'S environment before invoking echo. A clearer example may be: FOO=yes FOO=no awk 'BEGIN{print ENVIRON["FOO"]}' </dev/null echo $FOO That way we never used the syntax $FOO, so there is no possible confusion about which instance of which shell might have expanded it. It had to come from awk's environment. -- Brian K. White brian@aljex.com http://www.myspace.com/KEYofR +++++[>+++[>+++++>+++++++<<-]<-]>>+.>.+++++.+++++++.-.[>+<---]>++. filePro BBx Linux SCO FreeBSD #callahans Satriani Filk! -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
participants (7)
-
Brian K. White
-
David C. Rankin
-
Dr. Werner Fink
-
Duaine & Laura Hechler
-
Greg Freemyer
-
Patrick Shanahan
-
Per Jessen