1
varrr=0

while read line
do
    if [ $line -gt 500 -a $line -le 600 ]; then    # for lines 501-600
        echo $line >> 'file_out_${varrr}.ubi'
    fi
done << 'file_in_${varrr}.ubi'

file_in_${varrr}.ubi is a text file with around 1000 lines. I want to print lines 501-600 to new file.

Running this code leaves my Ubuntu terminal with a > symbol on a new line, as if I need to type another command to finish the loop. I can' figure out what is wrong with this loop though. Seems like it's complete. See any mistakes I've made? Thanks.

3 Answers 3

1

I'm only going to answer your specific question: it's because you used a heredoc << symbol, instead of a redirection <. Your last line should read:

done < 'file_in_${varrr}.ubi'

(observe the single <).

But then you'll realize that you have some quoting problems. So, your last line should read:

done < "file_in_${varrr}.ubi"

(observe the double quotes ").

Similarly, watch out your quotings in line 6. You should have this instead:

echo "$line" >> "file_out_${varrr}.ubi"

(double quotes " for file_out_${varrr}.ubi).

But then, this will not behave as you expect... Maybe this will do:

varrr=0
linenb=0
while IFS= read -r line; do
    ((++linenb))
    if ((linenb>500 && linenb<=600)); then    # for lines 501-600
        echo "$line" >> "file_out_${varrr}.ubi"
    fi
done < "file_in_${varrr}.ubi"

Hope this helps!

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, yeah I needed a counter, as well as the quotation marks you pointed out.
1

If you just want to print lines from 501 to 600, why don't you use the following?

awk 'NR>=501 && NR<=600' file_in > file_out

awk 'NR==n' myfile prints the line n of the file myfile. Then, you can use ranges as I writted above.

1 Comment

Thanks for the tip, I ended up using awk for this :)
1

You can simply use sed. It's the simplest tool for it and is cleaner and faster than a while loop with tests.

varrr=0
sed -n 501,600p "file_in_${varrr}.ubi" >> "file_out_${varrr}.ubi"

Or

varrr=0
sed -n 501,600p "file_in_${varrr}.ubi" > "file_out_${varrr}.ubi"

If you want to override existing data.

The mistake in your loop by the way is because you're not using a counter and comparing your line number by the line itself instead.

varrr=0
counter=0
while read line; do
    (( ++counter ))
    [[ counter -gt 500 && counter -le 600 ]] && echo "$line"
done < "file_in_${varrr}.ubi" > "file_out_${varrr}.ubi"

Noticeably you need to use < for input not << and place your variables around double quotes not single quotes.

1 Comment

Thanks, I'm new to bash and you helped me understand I need a counter. Totally needed. But I'll look into using sed or awk instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.