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 )
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
[...]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.
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
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)
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
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 (!).
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.
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)
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)
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)
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)
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)
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)
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)
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)