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.

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.

  • Perfect!, can it be WHITESPACE be replaced by tab? – CCC May 3 '18 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 '18 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 
  • 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 '18 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 '18 at 10:32
  • @CCC, do update both your question and expected result – RomanPerekhrest May 3 '18 at 10:32
  • @CCC, see my update – RomanPerekhrest May 3 '18 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 '18 at 10:54

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.