Convert perl-statement to /bin/sh shell

Hi,

I'm doing a small shellscript which is going to take each line in a "queue file" and do stuff to them. I can do the script easily, but I'd like this one to be a bit prettier.

Consider the following perl statement:

...
foreach my $line (@filedata) {
    my ($a, $b, $c) = split(/\t/, $line);
}
...

The queue file will have three "columns" seperated by a single tab (\t). I am wondering if it's possible to make a shellscript (bash/sh, please) similar to the above. I am guessing this would involve the use of sed or awk, but I'm afraid I'm not too good at regular expressions yet to pull it off.

queuefile="/path/to/queue.file"

while read line; do
   # Magic should be happening here :-)
done < $queuefile

One could definitely argue to keep it in perl if one know how to fix it - but I'd like to expand my shellscripting knowledge / bag of tricks a bit :slight_smile:

So - What would the best (and prettiest way) to mimic the perl code in bash/sh be?

Try this...

#!/bin/ksh
queuefile="/path/to/queue.file"

while read line; do
  set -A arr $line
  echo ${arr[0]} ${arr[1]} ${arr[2]}
done < $queuefile

regards,
Ahamed

1 Like
while read a b c; do echo $a; done <file
1 Like

Thanks to you both!

The solution from Ahamed works great in korn shell (but not SH), but still very nice to know.

I guess scripting never stops to surprise me, I didn't for a moment think it was as simple as supplying more variables to the loop.

Works like a charm!

while read uid mail; do
    echo "Uid=$uid, Mail=$mail" # Proof of concept
done < $myfile

Thanks to both of you!

None of the sh approaches provided are equivalent to the original perl, though they may be sufficiently close approximations for your needs. What follows is just a nitpicky analysis of the situation.

The perl is splitting on each occurence of a tab, nothing more. The sh approaches are splitting on contiguous whitespace (space, tab, and newline ... though a newline will never be seen since it's always consumed by the read).

In the perl version, consecutive tabs will yield empty fields. In the sh, they are taken as a single delimiter and will not produce an empty field.

In the perl version, if any of the tab-delimited fields contain a space character, the space will be part of a field. Under the sh approaches, the space will delimit a field and never be a member of it.

The sh read statements, due to how the sh handles IFS whitespace during field splitting, will discard leading and trailing whitespace (including tabs). The perl does not.

The sh read statement will treat a backslash before a newline as a line continuation sequence, stripping the backslash-newline pair from the data and will append the next line in the input. The perl will not treat that sequence specially. (This one can be easily fixed by using read's -r option.)

The perl list assignment will discard any extra fields generated by the split for which there are no variables allotted. The sh read statement will store all extra fields in the last variable.

Regards,
Alister