user3440108
user3440108

Reputation: 9

Is this bash for loop statement correct?

Here's the code:

totLines=$(wc -l < extractedips.txt)
for((a=0;a!=$totLines;a++))
{
  head -n$a extractedips.txt | nslookup >> ip_extracted.txt
}

I'm not sure what I'm doing wrong.

Upvotes: 0

Views: 327

Answers (3)

cb0
cb0

Reputation: 8623

Looks like you need sth. like this

for i in $(cat extractedips.txt)
do
echo $i | nslookup >> ip_extracted.txt
done

You don't need your counter variable, have a look at here for a better understanding.


Why I think your statement is wrong/not what you want and my answer don't deserve a negative voting :)

This statement will echo the first $a lines inside file extractedips.txt

head -n$a extractedips.txt | nslookup >> ip_extracted.txt

First up you have a file with ip's

cat extractedips.txt
127.0.0.1
192.168.0.1
173.194.44.88

Now we if you do

for a in 1 2 3
    head -n$a
done

the script will output

127.0.0.1
127.0.0.1
192.168.0.1
127.0.0.1
192.168.0.1
173.194.44.88

But I guess you need a list with all all ip's only once. If you don't need duplicate ip's you could also remove them. This will give you a sorted list with duplicates removed.

for a in $(sort test.txt | uniq -u)
do
echo $a | nslookup >> ip_extracted.txt
done

Update

As Aleks commented this will not work if the text file contain a '*' char. The shell will expand all files in current directory and echo the filename. I didn't know that :/

Upvotes: -3

that other guy
that other guy

Reputation: 123600

Yes! Despite what people are saying, this is a valid bash for loop!

Note, however, that it's a bash extension. It's not a valid sh for loop. You can not use this form of loop in e.g. a shell script declared with #!/bin/sh or run with sh yourscript.

The thing that doesn't work is your for loop contents.

  1. You're trying to get the n'th line, but head -n 42 gets the first 42 lines, not line number 42.
  2. You're using 0-based indexing, while head is 1-based.
  3. You're piping to nslookup, but nslookup expects an argument and not stdin.

The shortest fix to your problem is:

totLines=$(wc -l < extractedips.txt)
for ((a=1; a<=totLines; a++)); do
    nslookup "$(head -n "$a" extractedips.txt | tail -n 1)" >> ip_extracted.txt
done

However, the more efficient and canonical way of doing it is with a while read loop:

while IFS= read -r line
do
  nslookup "$line"
done  < extractedips.txt  > ip_extracted.txt

Upvotes: 3

Aleks-Daniel Jakimenko-A.
Aleks-Daniel Jakimenko-A.

Reputation: 10663

You should use do and done instead of curly braces.

Like this:

totLines=$(wc -l < extractedips.txt)
for ((a=0; a!=totLines; a++)); do
    head -n "$a" extractedips.txt | nslookup >> ip_extracted.txt
done

However, this code will do some weird stuff... Are you trying to pass it line by line into nslookup ?

What about this?

nslookup < extractedips.txt > ip_extracted.txt

Or you might want this:

while read -r line; do
    nslookup "$line" >> ip_extracted.txt
done < extractedips.txt

Upvotes: 1

Related Questions