-1

Having trouble using awk to output only the last record after a pattern match.

Each "record" would start with DATE end with dashed line.

I've tried the follow with no luck.

awk '/02\/21\/19/,/---/; END{print}' sample.file

but this just gives me all records, not just the last as I would have expected.

Sample data: I would call this two complete record. I just need the last one at any given time.

02/21/19 14:00:00 - 15:00:00
Total:
 ID        Total            Approved          Rejected
 All           1             0 (  0%)          1 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
123            1             0 (  0%)          1 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           1             0 (  0%)          1 (100%)
--------------------------------------------------------
02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)
-------------------------------------------------------- 

Also thought sed may work, but still get errors:

sed -n '/02\/21\/19/,/----/,$p'
sed: -e expression #1, char 20: unknown command: `,'

Expected output is the last record:

02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)

Any ideas?

  • What is the expected the output? – Nasir Riley Feb 23 at 17:29
  • 1
    I'm surprised you're getting any output at all: within single quotes, the shell DATE variable will not be expanded, so /$DATE/ will never match any line: that is searching for the end of line followed by the literal characters "D","A","T","E". – glenn jackman Feb 23 at 17:46
  • 1
    Also {END print} is an awk syntax error. Please show us your actual code. – glenn jackman Feb 23 at 17:47
  • The expected output would be the last record - in its entirety. – Tee Lin Feb 23 at 18:02
  • @TeeLin That is not the last record. Those are several records. What you probably mean is the last section. 2) Add the expected output to your question and format it with code so that it's easier to read. 3) Your awk syntax should be END'{print}'. 3) `sed is much better for what you are trying to get. Confirm this by adding it to the question. – Nasir Riley Feb 23 at 18:08
1

If your records are delimited by lines of --- and you want to print the last one of a supplied date, you can use something like

awk -v RS='\n-+' -v d='02/21/19' '$1 == d {x = $0} END {print x}'

Ex.

$ awk -v RS='\n-+' -v d='02/21/19' '$1 == d {x = $0} END {print x}' data

02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)

If you have GNU awk, and want to preserve the record separator, change x = $0 to x = $0 RT

  • This works but according to the expected output that was in his last comment before he removed it, he wants the dashed line at the end as well. – Nasir Riley Feb 23 at 18:23
  • Sorry for my miscomunication. just need the data in-between, not the delimiters themselves. This works as I wanted. THANK YOU!! Can I define date as variable? Such as $DATE if I use double quote? – Tee Lin Feb 23 at 18:37
  • @TeeLin yes you can pass a shell variable as the date like -v d="$DATE" – steeldriver Feb 23 at 18:40
0

In your command you have specified pattern match '/02/21/19 which includes first and last section too so it printed both sections

I tried with below 2 methods it worked fine

method1: awk '/^02\/21\/19 15/,/-------/{print $0}' file.txt

method2:sed -n '/02\/21\/19 15/,/---/p'  file.txt

output

02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)
--------------------------------------------------------
0

Your first sed command almost does the trick but it has syntax errors. If you want that last section, this will do it:

sed -n '/02\/21\/19 15:00:00 - 16:00:00/,/190/p' file.txt

Output:

02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)

1) -n tells sed not to automatically print the entirety.

2) The patterns within the forward slashes are what need to be matched. I put the data and time together as the first string as the the date by itself appears elsewhere in the file and the time probably does too as what you've provided is sample data. I then put 190 as the second pattern to match as the first place it appears is right before the dashed line.

0

Assuming you just want the last record in the input data:

$ awk '/\// { lines = $0; next } { lines = lines ORS $0 } END { print lines }' file
02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)
--------------------------------------------------------

This accumulates the lines of the input in the variable lines. Whenever a line matching / is found (a very naive way of detecting the line holding the date), the accumulated lines are cleared and set to the current line only, and we skip to the next cycle. At the end, the current accumulated lines are outputted.

The equivalent thing using sed:

$ sed -n '/\//{x;d;}; H; ${x;p;}' file
02/21/19 15:00:00 - 16:00:00
Total:
 ID        Total            Approved          Rejected
 All           7             0 (  0%)          7 (100%)

Total By Consumer:
 ID        Total            Approved          Rejected
3398            7             0 (  0%)          7 (100%)

Total By Supply:
 ID        Total            Approved          Rejected
3878           3             0 (  0%)          3 (100%)
190            4             0 (  0%)          4 (100%)
--------------------------------------------------------

This is step-by-step identical to the awk variation of the solution, but using the hold space instead of a variable to accumulate the lines of each record in.

  • I was trying same but I used lines=lines"\n"$0, but it didn't work, it was printing string $0 not it's value. – Prvt_Yadav Feb 24 at 9:27
  • @PRY Then you must have put $0 inside the quotes, possibly? – Kusalananda Feb 24 at 9:29

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.