Another IFS post, [ bourne SH only ] ?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Another IFS post, [ bourne SH only ] ?
# 1  
Old 11-30-2009
Another IFS post, [ bourne SH only ] ?

I know there's a large number of posts on this, I have read a number of them. But unable to find specifics.

Scrutinizer showed me a nice trick using IFS in a while loop in a BASH script, however when I went to hand in my work my tutor informed me that the criteria specifically states SHell script only, he also said I was "unable to do that" in regard to IFS. Looking through his examples in notes, it's all stuck in variable OLDIFS as per usual. My only problem is that I'm using that to parse a file in a while loop which then proceeds to call a number of functions.

So I am uncertain where to change my variable back to the old ifs, as so far I have tried different parts of my loop at the end of loop (which happens to be end of script) and the only other way I can see this working is if I change the variable at the start of each function. So I would have 8 declarations of IFS=$OLDIFS. And there's no guarantee that once i change it back to the OLDIFS in one function, once that function is complete and it enters back into my while loop that it will continue using the new IFS, so I would have to have another 8 declarations of OLDIFS=$IFS; IFS=":\n" at the end of each function as well...

the IFS=":\n" is only messing with my n's in my variable output eg: my add successful statement:
ADDEDPROD="new product added sucessfully"
comes out as " ew product added successfully"
and error for delete.
"unable to delete product, does not exist in database"
"u able to delete product, does ot exist in database"
and a few other error/output variables, everything else seems to work fine eg. Unix tools...

would be good if there was a way around this, anyone know?
or will i just have to change IFS back to OLDIFS at the start and end of every function?

another cygwin only related question for those that use it is, is there anyway to specify to use a SH script? because I tried with the IFS in while loop running in sh by just using
Code:
 sh ./script

however this seemed to work fine, so either the cygwin shell script isn't close enough to bourne shell, or the above line didn't open a new 'sh' shell or my teacher is misinformed. (i doubt that last part, but he is still human... I think Smilie)
Code:
tr '[:lower:]' '[:upper:]' < $file |
while IFS=: read cmd arg1 arg2 arg3; do
    case $cmd in
        ADD)  add "$arg1" "$arg2" "$arg3"
            ;;
        DELETE) delete "$arg1" "$arg2"
            ;;
        DISPLAYALL) displayall 
            ;;
        BRAND) fbrand "$arg1" 
            ;;
        PRODUCT) fproduct "$arg1"
            ;;
        *) echo "operation unknown"
            ;;
    esac
done
# this seems to be the only declaration that works in either shell

Code:
#this one gives me errors, but is apprently the right way to do it for bourne shell.
OLDIFS=$IFS
IFS=":\n"
tr '[:lower:]' '[:upper:]' < $file |
while read cmd arg1 arg2 arg3
do
    ...
    .......
    ...
done

# 2  
Old 11-30-2009
Quote:
[...]would be good if there was a way around this, anyone know?
or will i just have to change IFS back to OLDIFS at the start and end of every function?[...]
Well, it depends. The following syntax affects the IFS only for the read command inside the while loop, so you don't need to worry/restore the previous value of IFS for the statements after the loop.

Code:
while IFS= ...

Sometimes it's convenient to force a sub-shell execution to avoid affecting the current shell environment, but it depends on what exactly you' re trying to achieve.

Quote:
...this one gives me errors
Please post the exact command(s)/output (just copy/paste) you' re getting.
# 3  
Old 11-30-2009
Quote:
Originally Posted by radoulov
Well, it depends. The following syntax affects the IFS only for the read command inside the while loop, so you don't need to worry/restore the previous value of IFS for the statements after the loop.
I understand that, but that is only in the case of
Code:
 while IFS=: read ...

what I am saying is I have been told to do it differently in the format of:
Code:
OLDIFS=$IFS
IFS=":\n"

I am unsure why exactly I must use OLDIFS, but I assume it's a problem with sh? so far all tests I have done using IFS in while loop in sh, ash, bash, ksh all seem to work fine... So I really have no idea why my tutor seems to think otherwise, would have been helpful if I asked him to expand on this..


Quote:
Originally Posted by radoulov
Code:
while IFS= ...

Sometimes it's convenient to force a sub-shell execution to avoid affecting the current shell environment, but it depends on what exactly you' re trying to achieve.
I think the basic logic behind it is, 'sh' doesn't handle subshells very well, while bash/ksh etc do handle subshells fine. But the tutor is trying to teach us portable languages.

Quote:
Originally Posted by radoulov
Please post the exact command(s)/output (just copy/paste) you' re getting.
Like I have already mentioned my problems using OLDIFS variable is that my constant variables that i use to echo statements to standard output are missing the n's

Code:
 
 ew record added to database
 ew record added to database
 ew record added to database

however this is NOT for all my variables I have just checked over and tested a few of them, and they work, however addding, and failure to delete is leaving out n's, which seems wierd to me. You would think they all would not work, or they all would work. Not randomly willy nilly.
As you can see from my first post, I showed the while loop calling functions, so in the case of using OLDIFS/NEWIFS I assume those functions and variables called from there also use it. which is why i'm missing some "n's"

Code:
# arg errors
USAGE="usage: ./a3 -d dataBaseFilename -o operationsFilename"
ERRNOARG="error:Invalid command line not enough arguments"
ERRNOFILE="error:No operations file supplied"
ERRNOREAD="error:can't read"
ERROPEMPTY="error:Operations file empty"
ERRILLOPT="illegal options:"

# opt errors
ERRNOADD="unable to add"
ADDFORMAT="add:product:brand:isle"
ERRNODEL="not deleted does not exist"
DELFORMAT="delete:product:brand"
ERRNOBRAND="brand does not exist"
ERRNOPROD="does not exist"
ERROPERATE="unknown operation"
ERREXISTS="product already exists"

# common output
RECADDED="new record added to database"
DATAEMPTY="database is empty - nothing to display"
RECDELETE=":deleted"

readonly USAGE ERRNOARG ERRNOFILE ERRNOREAD ERROPEMPTY
readonly ERRILLOPT ERRNOADD ERRNODEL ERRNOBRAND ERRNOPROD
readonly ERROPERATE ERREXISTS RECADDED DATAEMPTY RECDELETE

DATAEMPTY seems to work, as does USAGE...
RECADDED does not

thanks for the help, if you need to see more of my code, eg where I am calling the variables from just ask Smilie

Last edited by gcampton; 11-30-2009 at 09:58 AM..
# 4  
Old 11-30-2009
Quote:
what I am saying is I have been told to do it differently in the format of:[...]
Did you ask him why he wants you to do so?

Quote:
I am unsure why exactly I must use OLDIFS, but I assume it's a problem with sh? so far all tests I have done using IFS in while loop in sh, ash, bash, ksh all seem to work fine... So I really have no idea why my tutor seems to think otherwise, would have been helpful if I asked him to expand on this..
There's a potential problem and it's not sh (Bourne Shell) specific. For instance, you may need the previous (most likely the default) value of IFS in case you need to use the shell word splitting latter in your script:

Code:
% cat s
puts(){ 
  printf 'the shell splits my args like this: \n'
  printf '\t\t%s\n' "$@"
  }
  
s=a:b:c ifs=$IFS IFS=: # save the current IFS and change it

puts $s

IFS=$ifs # restore default IFS  

puts $s

Code:
% sh s
the shell splits my args like this: 
                a
                b
                c
the shell splits my args like this: 
                a:b:c

Quote:
I think the basic logic behind it is, 'sh' doesn't handle subshells very well, while bash/ksh etc do handle subshells fine.[...]
Not at all, I meant to use a sub-shell only to avoid affecting the current shell environment:

Code:
% cat s
puts(){ 
  printf 'the shell splits my args like this: \n'
  printf '\t\t%s\n' "$@"
  }

s=a:b:c
  
( 
  IFS=: # inside a sub-shell because of the () 
  echo now inside ...
  puts $s

)

echo now outiside ...

puts $s

Code:
% ash s
now inside ...
the shell splits my args like this: 
                a
                b
                c
now outiside ...
the shell splits my args like this: 
                a:b:c

Quote:
Like I have already mentioned my problems using OLDIFS variable is that my constant variables that i use to echo statements to standard output are missing the n's[...]
I'm not sure if I understand what you're trying to say, but I suppose that you only need to quote your variables while echoing them:

Semi-right:
Code:
echo "$var"

Right:

Code:
printf '%s\n' "$var"

Often wrong:

Code:
echo $var

By post the exact command(s)/output I mean that we need to see:

+ the exact content of the script/code you're executing
+ the exact content of any input/output files (if any)
+ the exact command as issued on the command line and all the output you're getting (if any)
# 5  
Old 11-30-2009
I'm thinking that maybe I need to just stick the arguments into a temp $VAR or file
and then convert back to OLDIFS at bottom of loop and then execute function using the var/file as arguments, convert back to NEWIFS...

But, not quite sure if this would work seems a bit problematic to me.

Code:
OLDIFS=$IFS
IFS=":\n"

tr '[:lower:]' '[:upper:]' < $opfile |
while read cmd arg1 arg2 arg3 arg4
do
    case $cmd in
        ADD) cmdadd=`add $arg1 $arg2 $arg3 $arg4`
            ;;
        DELETE) cmddelete=`delete $arg1 $arg2 $arg3`
           ;;
        ETC) etc etc
            ;;
        *) echo "invalid"
    esac
    IFS=$OLDIFS
    #somehow execute the variable or file... maybe another case?
    IFS=":\n"
done



---------- Post updated at 12:30 AM ---------- Previous update was at 12:27 AM ----------

Ah ok what you said about the printf makes more sense...

ignore the above post, I'll play around with the output of my variables and see what happens. thanks
# 6  
Old 11-30-2009
Quote:
Originally Posted by gcampton
another cygwin only related question for those that use it is, is there anyway to specify to use a SH script?
Not sure what you're up to - but, in short, bash does not equal sh, at least not necessarily ... while on all of my (Debian) Linux boxes, sh is a link to bash, in all of my CygWin shells, sh is sh and bash is bash (!).
# 7  
Old 11-30-2009
Quote:
Originally Posted by dr.house
Not sure what you're up to - but, in short, bash does not equal sh, at least not necessarily ... while on all of my (Debian) Linux boxes, sh is a link to bash, in all of my CygWin shells, sh is sh and bash is bash (!).
This is on my Cygwin:

Code:
% uname
CYGWIN_NT-5.1
% type -a sh
sh is /usr/bin/sh
sh is /bin/sh
% /usr/bin/sh --version
GNU bash, version 3.2.49(22)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.
% /bin/sh --version
GNU bash, version 3.2.49(22)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.


Yes, it's often the case on GNU systems.
Just to add that when invoked as sh, bash has a slightly different behavior.

From man bash:

Code:
If  bash  is  invoked  with  the name sh, it tries to mimic the startup
       behavior of historical versions of sh as  closely  as  possible,  while
       conforming  to the POSIX standard as well.  When invoked as an interac-
       tive login shell, or a non-interactive shell with the  --login  option,
       it  first  attempts  to read and execute commands from /etc/profile and
       ~/.profile, in that order.  The  --noprofile  option  may  be  used  to
       inhibit  this  behavior.  When invoked as an interactive shell with the
       name sh, bash looks for the variable ENV, expands its value  if  it  is
       defined,  and uses the expanded value as the name of a file to read and
       execute.  Since a shell invoked as sh does not attempt to read and exe-
       cute  commands from any other startup files, the --rcfile option has no
       effect.  A non-interactive shell invoked with  the  name  sh  does  not
       attempt  to  read  any  other  startup files.  When invoked as sh, bash
       enters posix mode after the startup files are read.

Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Not able to understand IFS

Hi , i am in my initial learning phase of unix. i was going thru the function part. below is the example which was there but i am not able to understand logic and the use of IFS(internal field separator) lspath() { OLDIFS="$IFS" IFS=: for DIR in $PATH ; do echo $DIR ; done IFS="$OLDIFS"... (8 Replies)
Discussion started by: scriptor
8 Replies

2. Shell Programming and Scripting

Bash IFS

I am using bash and resetting IFS as below when reading the command line arguments. I do this so I can call my script as in Ex1. Ex1: ./synt2d-ray3dmod.bash --xsrc=12/20/30 This allows me to split both sides so that when I do "shift" I can get 12/20/30 What I do not understand is... (21 Replies)
Discussion started by: kristinu
21 Replies

3. Shell Programming and Scripting

Nested ifs

hi I keep getting an error with this nested if statement and am getting the error unexpected end of file, can anyone help me as to why this wont execute? #!/bin/bash #script to check wether the -i -v statements run correctly removeFile () { mv $1 $HOME/deleted }... (3 Replies)
Discussion started by: somersetdan
3 Replies

4. Shell Programming and Scripting

While loop and IFS?

Hi, while ; do echo "Please enter " read enter yyyy=${enter:0:4} mm=${enter:5:2} dd=${enter:8:2} result=`validateDate $yyyy $mm $dd` When does the loop keeping repeating till?? till 1 is equal to 1? what does this mean "${enter:0:4}" .The 0 and 4 part?? ... (3 Replies)
Discussion started by: sid22
3 Replies

5. Shell Programming and Scripting

How to use IFS in this scenario?

Given the scenario like this, if at all if have to use IFS on the below given example, how it should be used. IFS=/ eg: /xyz/123/348/file1 I want to use the last slash /file1 . So can anyone, suggest me how to pick the last "/" as a IFS. (4 Replies)
Discussion started by: raghunsi
4 Replies

6. Shell Programming and Scripting

read and IFS

Hi, This is out of curiosity: I wanted to extract year, month and date from a variable, and thought that combining read and IFS would help, but this doesn't work: echo "2010 10 12" | read y m d I could extract the parts of the date when separated by a -, and setting IFS in a subshell: ... (3 Replies)
Discussion started by: raphinou
3 Replies

7. Shell Programming and Scripting

regarding IFS=

hi i am a learner can some explain "export IFS=$(echo "\n\t\a")" i am not able to understand the functionality please help thanks Satya (1 Reply)
Discussion started by: Satyak
1 Replies

8. UNIX for Dummies Questions & Answers

Help on IFS command!

Hi! I am working in korn shell. I want to reset the dimiliter for the set command to "|" but instead of a command prompt return I am getting something as below After issuing the command I am getting this....as if the shell is expecting something else. Can anybody suggest what's the problem. ... (2 Replies)
Discussion started by: udiptya
2 Replies

9. UNIX for Dummies Questions & Answers

IFS variable

How can I set the value for IFS variable (2 Replies)
Discussion started by: mahabunta
2 Replies

10. UNIX for Dummies Questions & Answers

the IFS variable

Hi all, Ok os heres my situation. I have created a database style program that stores a persons info (name,address,phone number etc.) in a file ("database"). after i read in all the values above, i assign them to a line variable: line="$name^$address^$phonenum" >> phonebuk as you can see... (1 Reply)
Discussion started by: djt0506
1 Replies
Login or Register to Ask a Question