# file feed one line per argument

**URL:** <https://community.unix.com/t/file-feed-one-line-per-argument/139840>\
**Category:** UNIX for Dummies Questions & Answers\
**Created:** [October 5, 2001, 9:29pm UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840 "2001-10-05T21:29:05Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jpprial](https://community.unix.com/user_avatar/community.unix.com/jpprial/32/35_2.png) [@jpprial](https://community.unix.com/u/jpprial)\
**Post date:** [October 5, 2001, 9:29pm UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/1 "2001-10-05T21:29:05Z")

</div>

What tools can I use to accomplish this?  
I'm writing a shell script to analyze an inittab file. Here's a sample file:

init:3:initdefault:  
ioin::sysinit:/sbin/ioinitrc \>/dev/console 2\>&1  
tape::sysinit:/sbin/mtinit \> /dev/console 2\>&1  
muxi::sysinit:/sbin/dasetup \</dev/console \>/dev/console 2\>&1 # mux i  
nit  
stty::sysinit:/sbin/stty 9600 clocal icanon echo opost onlcr ixon icrn  
l ignpar \</dev/systty  
brc1::bootwait:/sbin/bcheckrc \</dev/console \>/dev/console 2\>&1 # fsck,  
etc.  
link::wait:/sbin/sh -c "/sbin/rm -f /dev/syscon; \  
/sbin/ln /dev/systty /dev/syscon" \>/dev/consol  
e 2\>&1  
cprt::bootwait:/sbin/cat /etc/copyright \>/dev/syscon # legal  
req  
sqnc::wait:/sbin/rc \</dev/console \>/dev/console 2\>&1 # syste  
m init  
#powf::powerwait:/sbin/powerfail \>/dev/console 2\>&1 # power  
fail  
cons:123456:respawn:/usr/sbin/getty console console # syste  
m console  
#ttp1:234:off:/usr/sbin/getty -h tty0p1 9600 # UPS now using this port  
#ttp2:234:respawn:/usr/sbin/getty -h tty0p2 9600  
#ttp3:234:respawn:/usr/sbin/getty -h tty0p3 9600  
#ttp4:234:respawn:/usr/sbin/getty -h tty0p4 9600  
#ttp5:234:respawn:/usr/sbin/getty -h tty0p5 9600  
ems1::bootwait:/sbin/rm -f /etc/opt/resmon/persistence/runlevel4\_flag  
ems2::bootwait:/sbin/cat \</dev/null \>/etc/opt/resmon/persistence/reboo  
t\_flag  
ems3:3456:wait:/usr/bin/touch /etc/opt/resmon/persistence/runlevel4\_fl  
ag  
ems4:3456:respawn:/etc/opt/resmon/lbin/p\_client  
ups::respawn:rtprio 0 /usr/lbin/ups\_mond -f /etc/ups\_conf

I want to read each line, and do various things, (i.e. ignore lines that begin with #)but what will send each line as an argument?

---

<div class="post-metadata">

**Author:** ![rwb1959](https://community.unix.com/user_avatar/community.unix.com/rwb1959/32/28_2.png) [@rwb1959](https://community.unix.com/u/rwb1959)\
**Post date:** [October 6, 2001, 10:45am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/2 "2001-10-06T10:45:05Z")

</div>

The basic strategy woudl be to read each  
line in a loop:

!#/bin/sh

while read iline  
do  
echo $iline  
done \< /etc/inittab

exit 0

In each iteration of the loop, you have the  
entire line in the variable $iline.  
From this point, the next step is to process  
each line in the loop however you need to.  
You can use awk for this task if you desire.

I just gave you the very basics as to not give  
away all the answers but it's a least a starting  
point 😉

---

<div class="post-metadata">

**Author:** ![jpprial](https://community.unix.com/user_avatar/community.unix.com/jpprial/32/35_2.png) [@jpprial](https://community.unix.com/u/jpprial)\
**Post date:** [October 7, 2001, 3:50am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/3 "2001-10-07T03:50:49Z")

</div>

thanks rwb, exactly what i was looking for. but i'm stuck there now. i was planning to use grep to anaylze inittab, you know, grep lines that begin with a # and ignore them, check the fields...  
but how can I pass each line as the argument to grep?  
I tried this way, but i'm not quite where I need to be yet:

#!/bin/ksh

while read iline  
do  
echo $iline|xargs  
echo $\*  
grep ^# $\*

as you can see, I"m using the Korn shell..

any more help will be greatly appreciated,

thanks again

---

<div class="post-metadata">

**Author:** ![rwb1959](https://community.unix.com/user_avatar/community.unix.com/rwb1959/32/28_2.png) [@rwb1959](https://community.unix.com/u/rwb1959)\
**Post date:** [October 7, 2001, 10:11am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/4 "2001-10-07T10:11:14Z")

</div>

I would use a different approach. I would  
use grep to remove all the lines that  
start with "#"...

!#/bin/ksh

# create a tmp file with all lines in /etc/inittab  
# that do not start with "#"  
grep -v ^# /etc/inittab \> /tmp/mytest.$$

#loop through each line in the tmp file  
while read iline  
do  
# this is where you would process $iline  
# using awk and/or sed is easiest IMHO  
...  
...  
done \< /tmp/mytest.$$

# clean up after yourself  
rm -f /tmp/mytest.$$

exit 0

...what you do in the processing of each line  
is dependent on what "and do various things"  
entails. I'd also recommend a careful reading  
of the grep man page. There's alot of good stuff  
you can do with it. Also, the following URL  
is a good online reference for AWK:  
[http://vectorsite.tripod.com/tsawk0.html](http://vectorsite.tripod.com/tsawk0.html)

---

<div class="post-metadata">

**Author:** ![jpprial](https://community.unix.com/user_avatar/community.unix.com/jpprial/32/35_2.png) [@jpprial](https://community.unix.com/u/jpprial)\
**Post date:** [October 7, 2001, 7:54pm UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/5 "2001-10-07T19:54:07Z")

</div>

I'll use sed and awk when I get more familiar with them, I think grep will work for what I need to do, here's my script so far, with some of the "various things" I want the loop to do included as comments. Your help has made a drastic improvement already, what will the next step be...

#!/bin/ksh

# Usage: chkinit (inittab file)

# This creates a temp file to work with,using all lines  
# in the inittab that do not begin with # (assumes the argument is an  
# inittab file) and all lines that are not blank

grep -v -e "^#" -e "^$" $1 \> /tmp/mytest.$$

# this will loop through each line in the tmp file

while read iline  
do  
# case (can I use case here... if so how?)  
# I would like to: \* ensure that all lines contain 4 fields  
# \* make sure the id field has from 1 to 4 chars  
# \* make sure that the run levels are valid for  
the process indicated  
done \< /tmp/mytest.$$

rm -f /tmp/mytest.$$

---

<div class="post-metadata">

**Author:** ![rwb1959](https://community.unix.com/user_avatar/community.unix.com/rwb1959/32/28_2.png) [@rwb1959](https://community.unix.com/u/rwb1959)\
**Post date:** [October 8, 2001, 8:59am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/6 "2001-10-08T08:59:52Z")

</div>

Well... I don't believe grep by itself will  
give you what you need. This is why I suggest  
awk. I myself would in fact use awk for this  
sort of thing. ksh itself does not provide  
good string handling capabilities (at least not  
without alot of excess work). For example,  
the resulting lines from /etc/initab may be  
somthing like...

1:2345:respawn:/sbin/mingetty tty1  
2:2345:respawn:/sbin/mingetty tty2  
3:2345:respawn:/sbin/mingetty tty3  
...  
...

...so here you can see you have 4 fields...  
id:runlevels:action:process  
...separated by a ":" and you need to examine  
these individually so you would need to  
separate each field into distinct variables.  
awk provides simple methods for doing this  
very thing (and much much more). You could  
perhaps use "case" against a single field  
variable (once extracted from the line) to  
apply rules that are defined as general for  
a given value. Special rules however will  
tend to create an overly complex script and  
more prone to errors.

Again, my recommendation would be to learn  
awk (at least the basics of it) and try some  
things. After that if you have more questions,  
I'm sure you can get answeres on this forum.🙂

---

<div class="post-metadata">

**Author:** ![Perderabo](https://community.unix.com/user_avatar/community.unix.com/perderabo/32/27_2.png) [@Perderabo](https://community.unix.com/u/Perderabo)\
**Post date:** [October 8, 2001, 10:59am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/7 "2001-10-08T10:59:29Z")

</div>

I would just use ksh by itself. It can read each record, split the record into fields, count the characters in a field, etc. In short, it can do everything you need.

Also, remember that lines are not the same as records in inittab. You can end a line with a backslash to continue the record on the next line. Your grep method doesn't handle this.

Here is some sample code to show the concept...

```nohighlight
#! /usr/bin/ksh

IFS=":"
while read id rstate action process ; do

# ignore comments
    [[$id = \#*]] && continue

# count fields
    ((nf=0))
    [[! -z $id]] && ((nf=nf+1))
    [[! -z $rstate]] && ((nf=nf+1))
    [[! -z $action]] && ((nf=nf+1))
    [[! -z $process]] && ((nf=nf+1))

# ignore all blanks
    (( ! nf )) && continue

    idlength=${#id}
    echo $id $idlength
done
exit 0

```

You should be able to code in any tests you want in place of that echo statement.

---

<div class="post-metadata">

**Author:** ![jpprial](https://community.unix.com/user_avatar/community.unix.com/jpprial/32/35_2.png) [@jpprial](https://community.unix.com/u/jpprial)\
**Post date:** [October 8, 2001, 5:26pm UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/8 "2001-10-08T17:26:20Z")

</div>

wow, thanks. that's getting there, but the -z won't allow for empty fields, which i think are legal, like this line:

ups::respawn:rtprio 0 /usr/lbin/ups\_mond -f /etc/ups\_conf

doesn't a blank in the runlevel field indicate this should run at all run levels?

---

<div class="post-metadata">

**Author:** ![Perderabo](https://community.unix.com/user_avatar/community.unix.com/perderabo/32/27_2.png) [@Perderabo](https://community.unix.com/u/Perderabo)\
**Post date:** [October 9, 2001, 9:22am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/9 "2001-10-09T09:22:18Z")

</div>

> [@](#):
>
> Originally posted by jpprial  
> wow, thanks. that's getting there, but the -z won't allow for empty fields, which i think are legal, like this line:
> 
> ups::respawn:rtprio 0 /usr/lbin/ups\_mond -f /etc/ups\_conf

Yeah, that line is legal and my code will not reject it. It this case nf will be 3 because there are 3 non-empty fields. Only records where nf is 0 are discarded, these are blank lines.

> [@](#):
>
> Originally posted by jpprial  
> doesn't a blank in the runlevel field indicate this should run at all run levels?[/b]

If you leave this field empty, it is the same as specifying "0123456", which means that it will not run in run level s.

---

<div class="post-metadata">

**Author:** ![jpprial](https://community.unix.com/user_avatar/community.unix.com/jpprial/32/35_2.png) [@jpprial](https://community.unix.com/u/jpprial)\
**Post date:** [October 9, 2001, 9:48am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/10 "2001-10-09T09:48:51Z")

</div>

I see that it works. But somehow I have to count the empty fields, to make sure that there are 4 fields, empty or not. I tried adding an "or" to the test statement (for fields 2 and 4, which can be blank), like this:

[[! -z $rstate -o -z $rstate]] && ((nf=nf+1))

but it complains about the -o option.

This is the test I put for length of id field,  
thanks again.

```
    idlength=$\{\#id\}      

    if [$idlength -ne 0 -a $idlength -le 4]; then
    :
    else
    echo "id field must be from 1 to 4 characters"
    fi

```

I also need some way to put the line number of a failing line into an echo statement...

---

<div class="post-metadata">

**Author:** ![Perderabo](https://community.unix.com/user_avatar/community.unix.com/perderabo/32/27_2.png) [@Perderabo](https://community.unix.com/u/Perderabo)\
**Post date:** [October 9, 2001, 10:22am UTC](https://community.unix.com/t/file-feed-one-line-per-argument/139840/11 "2001-10-09T10:22:03Z")

</div>

> [@](#):
>
> Originally posted by jpprial
> 
> [[! -z $rstate -o -z $rstate]] && ((nf=nf+1))
> 
> but it complains about the -o option.

Don't do that. The nf stuff is to detect completely blank lines. If you really wanted to unconditionally increment nf at this point, there is no need to add a test that cannot fail. ((nf=nf+1)) could be used all by itself. Add with ksh [[ or it handled by | not -o.

If you don't care whether or not the field rstate has something, just don't test it. Instead, test the stuff you do care about. You are already checking the id field for the number of characters. That leaves the action field. You can just add a "if [[-z $action]]" or maybe you'd rather get the length of the action field and see if it's non-zero.
