Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why is my IFS='=' broke?

16 views
Skip to first unread message

Bit Twister

unread,
Jan 21, 2013, 2:58:23 PM1/21/13
to
Wanting to convert my old kde desktop shortcut files into new kde files.

Seemed simple enough to get contents of what to save, and write to new file.

I do not understand why I can not save those field's string.

-----8<-----8<-----8<-----8< cut below this line----8<-----8<-----8<
#!/bin/bash
set -u
_in_fn="delete.me"
_Comment=""
_Exec=""
_Icon=""
_Name=""
_wd=""


cat > $_in_fn <<-EOF
[Desktop Entry]
Name=XTerm
GenericName=Terminal
Comment=%{Summary}
Exec=xterm -name Terminal
Icon=xterm-color
Terminal=false
Type=Application
StartupNotify=true
Categories=TerminalEmulator;System;Utility;
EOF


function parse_in_fn ()
{
while read -r line; do
set -- $(IFS='='; printf "%s" $line)
_wd=$1
shift
case $_wd in
Comment) _Comment="$@" ;;
Exec) _Exec="$@" ;;
Icon) _Icon="$@" ;;
Name) _Name="$@" ;;
esac
done < $_in_fn
} # end function parse_in_fn


parse_in_fn

echo Comment\) $_Comment
echo Exec\) $_Exec
echo Icon\) $_Icon
echo Name\) $_Name
#************************ end of convert_shortcuts **********************

Janis Papanagnou

unread,
Jan 21, 2013, 3:13:15 PM1/21/13
to
On 21.01.2013 20:58, Bit Twister wrote:
> Wanting to convert my old kde desktop shortcut files into new kde files.
>
> Seemed simple enough to get contents of what to save, and write to new file.
>
> I do not understand why I can not save those field's string.

I am not quite sure what output you actually expect, but why not just

function parse_in_fn
{
while IFS='=' read -r one two; do
case $one in
Comment) _Comment="$two" ;;
Exec) _Exec="$two" ;;
Icon) _Icon="$two" ;;
Name) _Name="$two" ;;
esac
done < $_in_fn
} # end function parse_in_fn


Janis

Bit Twister

unread,
Jan 21, 2013, 3:36:02 PM1/21/13
to
On Mon, 21 Jan 2013 21:13:15 +0100, Janis Papanagnou wrote:
>
> I am not quite sure what output you actually expect, but why not just
>
> function parse_in_fn
> {
> while IFS='=' read -r one two; do
> case $one in
> Comment) _Comment="$two" ;;

Because there is no telling what is on the rest of the line. If I read
Comment=there is no telling what Comment is = to.

Then the output will be

Comment) there is no telling what Comment is = to.


Current output is nothing. :(

Janis Papanagnou

unread,
Jan 21, 2013, 3:45:40 PM1/21/13
to
I don't understand what you are saying here. The output I get is exactly
what you have in your config data:

Comment) %{Summary}
Exec) xterm -name Terminal
Icon) xterm-color
Name) XTerm

Even if Comment has a string like "%{Summary}=hello=world" you will get
with above function exactly that output:

Comment) %{Summary}=hello=world
Exec) xterm -name Terminal
Icon) xterm-color
Name) XTerm

If that's not what you expected, then please tell us what the desired
output for your sample input is.

>
>
> Current output is nothing. :(

I guess you must be doing something wrong.

Janis

>

Janis Papanagnou

unread,
Jan 21, 2013, 3:50:54 PM1/21/13
to
On 21.01.2013 21:36, Bit Twister wrote:
> On Mon, 21 Jan 2013 21:13:15 +0100, Janis Papanagnou wrote:
>>
>> I am not quite sure what output you actually expect, but why not just
>>
>> function parse_in_fn
>> {
>> while IFS='=' read -r one two; do
>> case $one in
>> Comment) _Comment="$two" ;;
>
> Because there is no telling what is on the rest of the line. If I read
> Comment=there is no telling what Comment is = to.

You maybe want IFS including a space and discard the rest...?

while IFS='= ' read -r one two three; do

Jon LaBadie

unread,
Jan 21, 2013, 3:52:36 PM1/21/13
to
Its not a problem with IFS.

Bash will run your redirected while loop in a different environment
than the other code. Variables changed in that environment will
not be changed elsewhere.

Janis Papanagnou

unread,
Jan 21, 2013, 4:00:43 PM1/21/13
to
On 21.01.2013 21:52, Jon LaBadie wrote:
> On 01/21/2013 02:58 PM, Bit Twister wrote:
>> Wanting to convert my old kde desktop shortcut files into new kde files.
>>
>> Seemed simple enough to get contents of what to save, and write to new file.
>>
>> I do not understand why I can not save those field's string.
>>
>> -----8<-----8<-----8<-----8< cut below this line----8<-----8<-----8<
>> #!/bin/bash
[...]
>> function parse_in_fn ()
>> {
>> while read -r line; do
>> set -- $(IFS='='; printf "%s" $line)
>> _wd=$1
>> shift
>> case $_wd in
>> Comment) _Comment="$@" ;;
>> Exec) _Exec="$@" ;;
>> Icon) _Icon="$@" ;;
>> Name) _Name="$@" ;;
>> esac
>> done < $_in_fn
>> } # end function parse_in_fn
>>
>>
>> parse_in_fn
>>
>> echo Comment\) $_Comment
>> echo Exec\) $_Exec
>> echo Icon\) $_Icon
>> echo Name\) $_Name
>> #************************ end of convert_shortcuts **********************
>>
> Its not a problem with IFS.
>
> Bash will run your redirected while loop in a different environment
> than the other code. Variables changed in that environment will
> not be changed elsewhere.

This is wrong. Have a look at the slightly changed code that I posted
upthread; basically the same while loop construct, and the variables
will be visible below when the echos are executed.

Janis

>

Jon LaBadie

unread,
Jan 21, 2013, 4:12:06 PM1/21/13
to
On 01/21/2013 02:58 PM, Bit Twister wrote:
Ignoring my earlier comment, if you use read to both input and parse,
it seems to work.

function parse_in_fn ()
{
while IFS='=' read -r _wd _val; do
case $_wd in
Comment) _Comment="$_val" ;;
Exec) _Exec="$_val" ;;
Icon) _Icon="$_val" ;;
Name) _Name="$_val" ;;

Bit Twister

unread,
Jan 21, 2013, 4:17:15 PM1/21/13
to
On Mon, 21 Jan 2013 19:58:23 +0000 (UTC), Bit Twister wrote:

Solution was to backslash the =.

BROKE set -- $(IFS='='; printf "%s" $line)
FIXED set -- $(IFS='\='; printf "%s" $line)
--
The warranty and liability expired as you read this message.
If the above breaks your system, it's yours and you keep both pieces.
Practice safe computing. Backup the file before you change it.
Do a, man command_here or cat command_here, before using it.

Chris F.A. Johnson

unread,
Jan 21, 2013, 4:06:22 PM1/21/13
to
Only the original Bourne shell did that.

All modern shells execute redirected loops in the current
environment.


--
Chris F.A. Johnson, author <http://shell.cfajohnson.com/>
===================================================================
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)

Lew Pitcher

unread,
Jan 21, 2013, 4:33:44 PM1/21/13
to
On Monday 21 January 2013 14:58, in comp.unix.shell,
BitTw...@mouse-potato.com wrote:

> Wanting to convert my old kde desktop shortcut files into new kde files.
>
> Seemed simple enough to get contents of what to save, and write to new
> file.

To me, this looks like a job for awk

~/tmp $ cat desktop_file
[Desktop Entry]
Name=XTerm
GenericName=Terminal
Comment=%{Summary}
Exec=xterm -name Terminal
Icon=xterm-color
Terminal=false
Type=Application
StartupNotify=true
Categories=TerminalEmulator;System;Utility;

~/tmp $ awk -F = '$1~/^Comment$|^Exec$|^Icon$|^Name$/ {print $1 ") "$2 }'\
<desktop_file
Name) XTerm
Comment) %{Summary}
Exec) xterm -name Terminal
Icon) xterm-color

~/tmp $

HTH
--
Lew Pitcher
"In Skills, We Trust"

Dave Gibson

unread,
Jan 21, 2013, 6:27:11 PM1/21/13
to
Bit Twister <BitTw...@mouse-potato.com> wrote:
> Wanting to convert my old kde desktop shortcut files into new kde
> files.
>
> Seemed simple enough to get contents of what to save, and write to
> new file.
>
> I do not understand why I can not save those field's string.

> function parse_in_fn ()
> {
> while read -r line; do
> set -- $(IFS='='; printf "%s" $line)
> _wd=$1
> shift

printf re-uses the format string when there are more arguments than
format specifiers. With no spaces in the format string the arguments
will be concatenated in the output:

$ printf '%s' one two three ; echo
onetwothree

You're seeing something like this:

$ set -- $( line='one=two three' ; IFS='=' ; printf '%s' $line )
$ echo "$1" ; shift ; echo "$*"
onetwo
three

You either need a space after (or before) the %s or whitespace after
(or before) the first '=' in the input.

$ set -- $( line='one=two three' ; IFS='=' ; printf '%s ' $line )
$ echo "$1" ; shift ; echo "$*"
one
two three

Or you could follow Janis' advice.

Bit Twister

unread,
Jan 21, 2013, 6:46:26 PM1/21/13
to
On Mon, 21 Jan 2013 23:27:11 +0000, Dave Gibson wrote:
>
> printf re-uses the format string when there are more arguments than
> format specifiers. With no spaces in the format string the arguments
> will be concatenated in the output:

Nice to know. I think I went back and added a \n which might have hid
that problem, I think.

Had already gone back and replaced all printf with echo just to keep
it simple. :)

Thank you, and everyone else for their time.

Bit Twister

unread,
Jan 21, 2013, 6:49:45 PM1/21/13
to
On Mon, 21 Jan 2013 16:33:44 -0500, Lew Pitcher wrote:
> On Monday 21 January 2013 14:58, in comp.unix.shell,
> BitTw...@mouse-potato.com wrote:
>
>> Wanting to convert my old kde desktop shortcut files into new kde files.
>>
>> Seemed simple enough to get contents of what to save, and write to new
>> file.
>
> To me, this looks like a job for awk

I am impressed. I keep telling myself to take time to learn awk.

Save the code to look at later.

Thank you for your time.

Bit Twister

unread,
Jan 21, 2013, 6:59:56 PM1/21/13
to
On Mon, 21 Jan 2013 23:27:11 +0000, Dave Gibson wrote:

> printf re-uses the format string when there are more arguments than
> format specifiers. With no spaces in the format string the arguments
> will be concatenated in the output:
>
> $ printf '%s' one two three ; echo
> onetwothree

Yeah, saw that before posting my solution, which is probably
incorrect since I screwed up and made two changes at same time.
added \= and changed printf back to echo. Will have to go back
to see what is going with the real code.
0 new messages