1
votes

I'm looking to write a shell script that grabs a line number from a file using grep, and use that line numbers as head and tail for sed command to cut the file.

My script looks something like this:

head=$(grep -n -i -B 1 "^\s\+abcd" <sourcefilename> | head -n 1 | cut -d: -f1)
tail=$(grep -n -i  -B 1 " efgh" <sourcefilename>  | tail -n 1| cut -d: -f1)

if($head!=NULL)
then
        sed -n "$head,$tailp" <sourcefile>.txt > <newfile>.txt
fi

My goal, is to use first grep, and get the head line number when it matches the pattern, then use the second grep to get tail line number when it matches the pattern, and use those to as inputs for sed with -n switch and create a file that only has line numbers from head to tail.

If I execute it individually against the file, like

grep -n -i "^\s\+abcd" <filename> | head -n 1 | cut -d: -f1 , it gives me 11 and 
grep -n -i  " efgh" <filename>  | tail -n 1| cut -d: -f1 gives me 106. 

Then I used these numbers as inputs and do

sed -n 11,106 <sourcefile>.txt > <newfile>.txt 

it works perfectly. I'm trying to automate the process to have a script that can run against multiple files at once.

Also, the if statement with NULL means when grep doesn't return anything, just don't run the loop, which seems to also error out.

3
Please post some sample data we can work with. - James Brown
Please take a look: shellcheck.net - Cyrus
com.new.security.JXSecurityException: No certificates encoded in supported ways were found at com.tibco.security.CertUtils.streamToCerts(CertUtils.java:634) at com.tibco.ae.tools.palettes.generalpalette.ImportTrustedCertCommand.buttonPressed(ImportTrustedCertAction.java:133) at com.tibco.ae.designerapi.forms.ConfigForm.actionPerformed(ConfigForm.java:1326) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995) at com.tibco.security.CertUtils.streamToCerts(CertUtils.java:626) ... 86 more - Tk_93
For example there is this above stack trace. Use: grep -n -i "^\s\+at" sample.txt | head -n 1 | cut -d: -f1 grep -n -i " more" sample.txt | tail -n 1| cut -d: -f1 - Tk_93
$tailp is trying to expand a variable named tailp. If you want the value in the variable tail followed by a p, use ${tail}p - William Pursell

3 Answers

0
votes

You could probably solve that with awk only. First some data:

$ cat file
1
2
3
4
5
$ awk '/2/,/4/' file
2
3
4

You could replace the 2 and 4 with your proper regexen for the head and the tail.

Edit: an example of grep -B 1:

$ awk '/2/{f=1;print p} f{print} /4/{f=""} {p=$0}' file
1
2
3
4
0
votes

You don't need grep to search patterns, you can use sed or awk only:

sed -nE '/^\s+abcd/,/ efgh/p' sourcefile.txt

or

awk '/^\s+abcd/,/ efgh/{print}' sourcefile.txt

or more simple (by default awk just print lines)

awk '/^\s+abcd/,/ efgh/' sourcefile.txt

/pattern1/,/pattern2/{commands} common for sed and awk to work with lines between /pattern1/ and /pattern2/. In your case you just print output for.

0
votes

sed -n "$linenum,\$p" $infile >> source.csv

This actually worked for me with the sample data. It get me all the lines starting from head till end of file.