620
Comment:
|
1808
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
[[Anchor(faq11)]] | <<Anchor(faq11)>> |
Line 3: | Line 3: |
The dirty (but not quick) way would be {{{sed -n ${n}p "$file"}}} but this reads the whole input file, even if you only wanted the third line. | The dirty (but not quick) way would be: |
Line 5: | Line 5: |
The following {{{sed}}} command line reads a file printing nothing (-n). At line $n the command "p" is run, printing it, with a "q" afterwards: quit the program. | {{{ sed -n ${n}p "$file" }}} but this reads the whole input file, even if you only wanted the third line. This one avoids that problem: |
Line 10: | Line 15: |
At line $n the command "p" is run, printing it, with a "q" afterwards: quit the program. | |
Line 11: | Line 17: |
Another way, more obvious to some, is to grab the last line from a listing of the first n lines: | Another way, more obvious to some, is to grab the last line from a listing of the first ''n'' lines: |
Line 13: | Line 20: |
head -n $n $file | tail -n 1 | head -n $n $file | tail -n 1 |
Line 15: | Line 22: |
Another approach, using [[AWK]]: | |
Line 16: | Line 24: |
Using awk: | |
Line 18: | Line 25: |
awk 'NR==n{print;exit}' file | awk "NR==$n{print;exit}" file |
Line 20: | Line 27: |
If you want more than one line, it's pretty easy to adapt any of the previous methods: {{{ x=3 y=4 sed -n "$x,${y}p;${y}q;" "$file" # Print lines $x to $y; quit after $y. head -n $y "$file" | tail -n $((y - x + 1)) # Same head -n $y "$file" | tail -n +$x # If your tail supports it awk "NR>=$x{print} NR==$y{exit}" "$file" # Same }}} In Bash 4, this can also be done with mapfile builtin: {{{ mapfile -ts $((n-1)) -n 1 echo "${MAPFILE[0]}" }}} By changing the value of argument for -n, you can get more than one line in the array MAPFILE. === Note === In most cases, you should sanitize your variable n to be sure, that it's not containing any of non-digits, before feeding it to sed or awk. You can do it with such simple code: {{{ # Bash n=${n//[!0-9]/} # POSIX n=$(printf "%s" "$n"|tr -cd '0-9') }}} . One can argue that an `n` value of `Five brown horses with 3 feet and 9 little piggies.` should yield an error rather than silently behave as though it was really `39`. If you want to code safe, quote your expansions and be done with it. --[[Lhunath]] ---- CategoryShell |
How can I print the n'th line of a file?
The dirty (but not quick) way would be:
sed -n ${n}p "$file"
but this reads the whole input file, even if you only wanted the third line.
This one avoids that problem:
sed -n "$n{p;q;}" "$file"
At line $n the command "p" is run, printing it, with a "q" afterwards: quit the program.
Another way, more obvious to some, is to grab the last line from a listing of the first n lines:
head -n $n $file | tail -n 1
Another approach, using AWK:
awk "NR==$n{print;exit}" file
If you want more than one line, it's pretty easy to adapt any of the previous methods:
x=3 y=4 sed -n "$x,${y}p;${y}q;" "$file" # Print lines $x to $y; quit after $y. head -n $y "$file" | tail -n $((y - x + 1)) # Same head -n $y "$file" | tail -n +$x # If your tail supports it awk "NR>=$x{print} NR==$y{exit}" "$file" # Same
In Bash 4, this can also be done with mapfile builtin:
mapfile -ts $((n-1)) -n 1 echo "${MAPFILE[0]}"
By changing the value of argument for -n, you can get more than one line in the array MAPFILE.
Note
In most cases, you should sanitize your variable n to be sure, that it's not containing any of non-digits, before feeding it to sed or awk. You can do it with such simple code:
# Bash n=${n//[!0-9]/} # POSIX n=$(printf "%s" "$n"|tr -cd '0-9')
One can argue that an n value of Five brown horses with 3 feet and 9 little piggies. should yield an error rather than silently behave as though it was really 39. If you want to code safe, quote your expansions and be done with it. --Lhunath