0

I have a file in which I want to print all the lines between two patterns. Pattern1 = # Begin TRACE A Data and Pattern 2 =# Done Data $capture, I want to print every line between pattern1 and pattern2.

File 1:

# Lower Limit 
LIMIT_FLAG=0
LIMIT_POINT0=2884982910000.000000 -102800 -1
LIMIT_POINT1=2892982910000.000000 -102800 -1

# Limit Done

# Begin SPA Emission Mask
MASK SEGMENTS=0
MASK REFERENCE MODE=0
MASK REFERENCE LEVEL=0
MASK CENTER FREQUENCY=0
**
# SPA Emission Mask Done

# Begin SPA Data
<AP    P_DATA>

** # Begin TRACE A Data **  
P_0=-103.976000 , 2884.982910 MHz  
P_1=-103.580000 , 2884.997456 MHz  
P_2=-103.748000 , 2885.012001 MHz  
P_3=-104.020000 , 2885.026547 MHz  
P_4=-103.472000 , 2885.041092 MHz  
P_5=-103.720000 , 2885.055638 MHz  
P_6=-103.752000 , 2885.070183 MHz  
P_7=-103.512000 , 2885.084729 MHz  
P_8=-103.664000 , 2885.099274 MHz  
P_9=-103.948000 , 2885.113820 MHz  
P_10=-103.720000 , 2885.128365 MHz  
P_11=-103.480000 , 2885.142911 

# Done Data $capture
# Begin SPA Emission Mask
MASK SEGMENTS=0
MASK REFERENCE MODE=0
MASK REFERENCE LEVEL=0
MASK CENTER FREQUENCY=0

# End SPA Data
<APP_DATA_END>

# End SPA Data
<APP_DATA_END>

Expected output:

-103.976000   2884.982910
-103.580000   2884.997456
-103.748000   2885.012001
-104.020000   2885.026547
-103.472000   2885.041092
....
....

No extra lines or blank lines should be printed but just the lines data.

2 Answers 2

1
sed -n '/# Begin TRACE A Data/,/# Done Data $capture/{s/ MHz//;s/,/ /;s/.*=//p;}' filename
  • /pattern1/,/pattern2/ selects only the lines from the first to the second pattern, so everything inside {} is executed only for the range
  • s/ MHz// removes the trailing unit
  • s/,/ / replaces the comma with a whitespace
  • s/.*=//p removes everything upto the = and prints the pattern, so only lines in the range with that = will get printed (option -n suppresses default output)

Actually, for your example data, you could also do

sed -n 's/ MHz//;s/.*=//;s/,/ /p'

because only the lines you want contain a comma.

2
  • Perfect!, can it be WHITESPACE be replaced by tab?
    – CCC
    May 3, 2018 at 11:16
  • Sure, in this case you probably want to replace the comma along with the spaces before and after. With GNU sed, you can use s/ , /\t/, but this is not standard, so better use a literal TAB instead of \t (in most shells you can enter a literal TAB by preceeding it with ctrl-V.
    – Philippos
    May 3, 2018 at 11:21
1

Awk solution:

awk '/# Begin TRACE A Data/{ f = 1; next }
     /# Done Data \$capture/{ f = 0 }
     NF && f{ gsub(/^P.+=|,| MHz/, ""); print }' file

The output:

-103.976000  2884.982910  
-103.580000  2884.997456  
-103.748000  2885.012001  
-104.020000  2885.026547  
-103.472000  2885.041092  
-103.720000  2885.055638  
-103.752000  2885.070183  
-103.512000  2885.084729  
-103.664000  2885.099274  
-103.948000  2885.113820  
-103.720000  2885.128365  
-103.480000  2885.142911 
7
  • That's nice, I made a mistake in asking. The data file further contains lines having string '# End SPA Data' after pattern2, I don't want that to be printed. Also in the output can I just get all the lines with numbers ex:- 103.9760000 2884.982910 tab-separated and ignore other characters?
    – CCC
    May 3, 2018 at 10:28
  • I ran this command awk '/TRACE A Data/,/Data Done/' 11-wm-2db.spa |grep -v 'Data' but I want output to be two columns with P_0= and comma and MHz ignored with two columns tab-separated So, output should be -103.9760000 2884.983910 -103.5800000 2884.997456 line-wise .. ..
    – CCC
    May 3, 2018 at 10:32
  • @CCC, do update both your question and expected result May 3, 2018 at 10:32
  • @CCC, see my update May 3, 2018 at 10:46
  • It is still printing the lines after pattern2 ( # Data Done $capture), they are the lines <APP_DATA_END> and # End SPA Data. Also, please will you explain the code?
    – CCC
    May 3, 2018 at 10:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .