awk problem

I have two file one file contain student data

101|suresh|45|25|45|chennai 
102|gopal|89|78|50|hyd 
103|lakshmi|45|65|35|hyd
104|kavitha|65|68|40|banglore 
105|tiru|35|42|30|chennai

another file contain the program is

while read line
do
var=$(awk -F "|" '{if ( NR == 1 ) print $0 }')
echo "$var"
done < student.txt

while executing which print the second record..pls tel me the exact problem
if i write the code

awk -F "|" '{if ( NR == 1 ) print $0 }' 

which give the output...pls help me

where is the input for awk command ?

where u specified ?

firstly I read through while loop....see that done < file name...

---------- Post updated at 12:38 PM ---------- Previous update was at 12:36 PM ----------

awk -F "|" '{if ( NR == 1 ) print $0 }' student.txt

which gives the first record of 101|suresh file ...

---------- Post updated at 12:39 PM ---------- Previous update was at 12:38 PM ----------

but for this cod which give second output

while read line do var=$(awk -F "|" '{if ( NR == 1 ) print $0 }') echo "$var" done < student.txt
1 Like

The whole idea is flawed. What is wrong with

[mute@geek ~/test]$ awk -F"|" 'NR == 1' students.txt
101|suresh|45|25|45|chennai

You are reading by redirection in bash each line into $line, you exec awk for each line but never send awk the line. I suppose you'd need to $(echo $line | awk) but then the NR would always be 1 since it's a separate process each time. You gobble the first line with the 'read' statement, then awk is opened upon stdin, where it does get the rest of the file by redirection. If you keep the loop (bad idea anyway) but don't read, you can get all of it I guess

[mute@geek ~/test]$ while [ -n "$var" ]; do var=$(awk -F "|" '{ print NR "  " $0 }'); echo "$var"; done < students.txt
1  101|suresh|45|25|45|chennai
2  102|gopal|89|78|50|hyd
3  103|lakshmi|45|65|35|hyd
4  104|kavitha|65|68|40|banglore
5  105|tiru|35|42|30|chennai
1 Like

dude it is not working,can u give another idea?

Sure. Do you have your newly modified code to post, or an example of what you're trying to do with the data?

I tried the code which you have given,,but what is
while [ -n "$var" ] loop coding..how this execute.last one week I am learning UNIX,pls help me

I was showing you that you don't need a loop with redirection, because you only need to run awk once to get the first line.

[ -n "$var" ]

the "[" is a built-in for "test". try "help test" in your shell. this runs the loop once, because it just tests if var doesn't exist.

I think the easiest way though, if you want to print the first line in a file is

head -1 file

Awk is printing the second line from file 1 because you have not supplied any input to the awk command. By default, with no input supplied, awk reads from stdin. The way that Ksh and bash function, anything reading from stdin within a while with redirection like this, will also read from the redirected input. So, the while loop reads the first line, and when awk is called it reads the rest, starting with line 2.

If you run this simple script, you will notice that the awk prints all lines except the first, and the while exits after running the awk only once because the end of stdin is reached:

#!/usr/bin/env ksh
while read x
do
    echo "read line: $x"
    echo "running awk"
    awk '{print ">>> " $0;}'
done <t1.data
exit

You are seeing awk print only one line because you have added the test NR == 1 ; this is making the behaviour a bit more difficult to understand.

If your goal is to read each line from file 1 (the student records) and use awk to do some processing on each, maybe you should just let awk parse the file directly rather than reading each line into a shell variable and attempting to work on it with awk. It is certainly more efficient to let awk do the file i/o in this case. Here's a sample:

awk -F \| '
    {
        printf( "student %s has student id %d and lives in %s\n", $2, $1, $NF );
    }
' <t1.data

I made assumptions about your input data and am sorry if they aren't correct, but this should provide enough illustration to get going again.

And for the record, '[' is NOT a shell built-in. It is a binary, or somtimes a sym-link to the test command, and generally 'lives' in /usr/bin. The [[ expression ]] construct in Kshell and bash is built-in. Both expression types have similar, yet very different, functionality and using test is not as efficient.

1 Like

Thanks for this useful posts...and what is the diff b/w if (---- ) and if [[--- ]]

In Korn Shell and bash, the constructs if [[ expression ]] and if (( expression )) are interpreted by the shell. The if [ expression ] is actually a command that the shell executes; the '[' is the command name.

The first noticeable difference is the overhead that the '[' command requires as a new process must be started, the binary loaded, and then cleaned up all to evaluate the expression to determine true or false. If you don't need to use the single bracket command, it is much more efficient to use the built-in evaluation.

Something that isn't obvious is that Kshell treats the right hand side of the expression as a pattern; the test (or [ command) does not. This allows you to do something like this:

if  [[  $var_name == *"foo"* ]]

Bash might do this too; I'm not a heavy bash user so I don't know for sure.

The (( expression )) is meant for numerical expressions while the double bracketed version is meant for string expressions. While this is still supported:

if [[ $var -gt 10 ]]

Kshell will give a warning (when run with -n) that it is obsolete. This would be the preferred syntax:

if (( $var > 10 ))

I hope this has answered your question.

1 Like

from employee table,need to segregate to their respective departments and to store in separate file,can any body help