How to Read N-Th Line from a Text File in Bash

Bash tool to get nth line from a file

head and pipe with tail will be slow for a huge file. I would suggest sed like this:

sed 'NUMq;d' file

Where NUM is the number of the line you want to print; so, for example, sed '10q;d' file to print the 10th line of file.

Explanation:

NUMq will quit immediately when the line number is NUM.

d will delete the line instead of printing it; this is inhibited on the last line because the q causes the rest of the script to be skipped when quitting.

If you have NUM in a variable, you will want to use double quotes instead of single:

sed "${NUM}q;d" file

How do I read the Nth line of a file and print it to a new file?

Sed can help you.

Recall that sed will normally process all lines in a file AND print each line in the file.

You can turn off that feature, and have sed only print lines of interest by matching a pattern or line number.

So, to print the 2nd line of file 2, you can say

sed -n '2p' file2 > newFile2

To print the 2nd line and then stop processing add the q (for quit) command (you also need braces to group the 2 commands together), i.e.

sed -n '2{p;q;}' file2 > newFile2

(if you are processing large files, this can be quite a time saving).

To make that more general, you can change the number to a variable that will hold a number, i.e.

  lineNo=3
sed -n "${lineNo}{p;q;}" file3 > newFile3

If you want all of your sliced lines to go into 1 file, then use the shells 'append-redirection', i.e.

 for lineNo in 1 2 3 4 5 ; do
sed -n "${lineNo}{p;q;}" file${lineNo} >> aggregateFile
done

The other postings, with using the results of find ... to drive your filelist, are an excellent approach.

I hope this helps.

How to read n-th line from a text file in bash?

Using head and tail

$ head -2 inputFile | tail -1
5 6 7 8

OR

a generalized version

$ line=2
$ head -"$line" input | tail -1
5 6 7 8

Using sed

$ sed -n '2 p' input
5 6 7 8
$ sed -n "$line p" input
5 6 7 8

What it does?

  • -n suppresses normal printing of pattern space.

  • '2 p' specifies the line number, 2 or ($line for more general), p commands to print the current patternspace

  • input input file

Edit

To get the output to some variable use some command substitution techniques.

$ content=`sed -n "$line p" input`
$ echo $content
5 6 7 8

OR

$ content=$(sed -n "$line p" input)
$ echo $content
5 6 7 8

To obtain the output to a bash array

$ content= ( $(sed -n "$line p" input) )
$ echo ${content[0]}
5
$ echo ${content[1]}
6

Using awk

Perhaps an awk solution might look like

$  awk -v line=$line 'NR==line' input
5 6 7 8

Thanks to Fredrik Pihl for the suggestion.

How to get the nth line from a file and save the result to a variable

sed '2q;d' file

prints the second line in file to the terminal.

To populate a variable with it, use bash's command expansion feature:

$ var=$(sed '2q;d' file)
$ echo "$var"
this is second line

find text in file starting from nth line onwards, using shell script

It would be best to do this entirely in awk since you are already using awk to slice the file.

Example:

tgt="def"
n=3

awk -v tgt="$tgt" -v n="$n" '
BEGIN{flag="false"}
FNR>=n && index($0,tgt){
flag="true"
exit
}
END{print flag}' file

Alternatively, you can make a pipe and then inspect $? to see if grep found your match:

tgt="def"
n=2

tail -n "+$n" file | grep "$tgt" >/dev/null

Now $? will be 0 if the grep finds the pattern and 1 if it is not found. Then you can set a flag like so:

flag="false"
tail -n "+$n" file | grep "$tgt" >/dev/null
[ $? ] && flag="true"

Now flag is set true / false based on the grep. The command tail -n +[some number] file will print the file contents from the absolute line number onward.

For large files, the awk is significantly more efficient since it exits on the first match.


Edit based on update.

The issue is setting a Bash flag to true or false based on a process.

The $? Special Parameter is set based on the exit status of the most recently executed foreground pipeline. So pick your method to slice the file and detect the string and then set the flag in your script based on $? immediately after the pipe. Be aware that testing $? resets $? before it is tested -- so you either need to capture the value of $? before the test or use it in the pipeline itself.

These methods work:

1) Capture $? and test:

awk -v tgt="$tgt" -v n="$n" -v flag=1 '
FNR>=n && index($0,tgt){
flag=0
exit
}
END{ exit flag }
' ./testtext.txt
res=$?
[ $res -eq 1 ] && flagz=false || flagz=true

2) Capture a string result and test that:

res=$(awk -v tgt="$tgt" -v n="$n" -v flag="false" '
FNR>=n && index($0,tgt) {
flag="true"
exit
}
END{ print flag }' ./testtext.txt)

[ $res = "false" ] && flagz=false || flagz=true

3) Use a pipe and test in the pipe:

tail -n "+$n" file | grep "$tgt" >/dev/null && flagz=true || flagz=false 

My preference is 3 for small files and 2 for big files.

Get specific line from text file using just shell script

sed:

sed '5!d' file

awk:

awk 'NR==5' file

fetch nth line of a text file using non-interactive shell script

An efficient way to print nth line from a file (especially suited for large files):

sed '2q;d' file

This sed command quits just after printing 2nd line rather than reading file till the end.

To store this in a variable:

line=$(sed '2q;d' file)

OR using a variable for line #:

n=2
line=$(sed $n'q;d' file)

UPDATE:

Java Code:

try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "/full/path/of/myScript.sh" );
Process pr = pb.start();
InputStreamReader isr = new InputStreamReader(pr.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = pr.waitFor();
System.out.println("exitVal: " + exitVal);
} catch(Exception e) { e.printStackTrace(); }

Shell script:

f=$(dirname $0)/edit.txt
read -r i < "$f"
echo "session is: $i"

echo -n "file path is: "
sed '2q;d' "$f"

how to print the nth line from the end of a file in bash?

The quick and easy way is tail -n $n file | head -n 1.

A more fun way with awk is:

awk -v n=$n '{x[NR%n]=$0}END{print x[(NR+1)%n]}' file

If you have fewer than n lines, the tail | head method will print the first line of the file, the awk way will print a blank line.



Related Topics



Leave a reply



Submit