1

I've already extracted the line numbers needed from the input file (i.e 1 through N). I now need to be able to use the input file with this 1-through-N to output to a new file. The pattern matching has already occurred in a previous function which extracted the line numbers from the input file. Now I need to take this range of numbers using the input file and output that range into a new file. I don't need to do any pattern matching, just need to do 1-through-N to a new file.

I'm currently using a bash script with Awk extracting the necessary information to generate the ranged data from the input file. Now I need to take that rage and create a new file (using the input file) from 1 to N.

I've tried

sed -i '1,'"$N" input.txt > input.log

to go from 1 to N using my input file input.txt and outputting to input.log file but I get the following error:

sed: -e expression #1, char 3: missing command

The line of code above is within a bash script.

2
  • When I first read this, I assumed that the line number list 1..N was non-contiguous (because "line numbers" was in the plural). But the responses you accept just work for all lines up to N. The sed, awk and perl tools all have matching capabilities that suggest you could combine extracting N from the file with separating the data, avoiding reading the input twice. Jan 14 '20 at 12:55
  • Sounds like you're going about this the wrong way, i.e. using "pattern matching" to get line numbers and then printing lines based on those line numbers. If you post a question with concise, testable sample input (i.e. the files before that first phase you've already got "working") and expected output we can help you do whatever it is you're trying to do the right way.
    – Ed Morton
    Jan 14 '20 at 16:09
5

head seems like the best tool for the job:

head -n "$N" input.txt > input.log

With sed, you need to specify a command; based on your approach, that would be the p command and the -n option so it doesn’t print the pattern space by default:

sed -n "1,${N}p" input.txt > input.log

but

sed "$N q" input.txt > input.log

would be more efficient, only reading the first N lines and stopping (which is also what head does) instead of reading the complete file (which is what sed "1,${N}p" does).

These approaches only produce the same output for N greater than or equal to 1; if it’s less than 1, the behaviours will differ.

0
1

Would

sed "${N}q" file

do what you need?

1

For lines from M to N (assuming M <= N):

head -n N input.txt | tail -n $(( N - M + 1))

or

cat input.txt | head -n N | tail -n $(( N - M + 1))

The latter form can be used for any stream

0

Other possibilities

sed -n ''"$N"',$ !p' file

sed '1,'"$N"' !d' file

awk 'FNR <= '"$N"'' file

perl -ne'1..'"$N"' and print' file
0

Using double quotes are "no quotes" make things simpler:

head -$N ex
sed "$N q" ex
sed -n "1,$N p" ex
awk "NR <= $N" ex
perl -ne "print if $. <= $N" ex
grep -m $N . ex

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.