2

I have a problem similar to Print text before and after match, from a specific beginning and to an ending string but with a twist.

My file is a large CSV which was manually constructed. It contains the string "WAP" many times. My job is to detect all instances of the string WAP and print the character that comes two characters before each match, so long as that character is a number.

I've never needed to do string searching like this, so any guidance you can offer will be majorly helpful to my task. Thanks all.

~ daniel ~

Sample from spreadsheet: ,x,x,x,x,x,xx,Yes,"1 WAP, other stuff, other stuff",no,x

Intended output from that line: 1

this was how far I got because i've never had to use awk before:

awk '/WAP/{print}' ~/spreadsheets/waps.csv

which seems to want to print each matching line. What I think I need to do is to keep a loop running that accumulates characters up until the WAP is matched, then grabs the character two earlier. But last time I did that was in university in 1999.

4
  • provide sample input, sample output.
    – Dudi Boy
    Jun 11 '19 at 20:08
  • it'll generally look like this: x,x,x,x,xx,Yes,"1 WAP New, (Box with label for Cisco 1921 router and Cisco 2960)" Sometimes the stuff preceding it is not consistent. I need to be able to read line by line and pull out the 1 for an audit I'm performing of my department's spend-versus-completion on a $10m project. I can match the string WAP just fine but I can't find a creative way to grab just the preceding two characters, which is how I'm going to count how many WAPs we've already sent to be installed at our offices. Thanks Jun 11 '19 at 20:09
  • please post 2 sample input lines into question. so we can test a solution.
    – Dudi Boy
    Jun 11 '19 at 20:17
  • wrt It contains the string "WAP" many times - can it occur multiple times in one line? If so include that in your sample input/output.
    – Ed Morton
    Jun 12 '19 at 12:23
1

Assuming WAP can only occur once per line I think this is probably what you really want. Given this input file:

$ cat file
,x,x,x,x,x,xx,Yes,7,WAP,no,x
,x,x,x,x,x,xx,Yes,3 WAP,no,x
,x,x,x,x,x,xx,Yes,"1 WAP",no,x

With GNU awk:

$ awk 'match($0,/([0-9])[^,]WAP/,a){print a[1]}' file
3
1

With any awk:

$ awk 'match($0,/[0-9][^,]WAP/){print substr($0,RSTART,1)}' file
3
1
0

Here is a sample awk script.

 awk '/..WAP../{print substr($0, index($0,"WAP") - 2, 7);}' input.csv

sample input:

junk
line 1 12WAP34 678
another line  abWAPcdefg
WAP123
junk WAP

output:

12WAP34
abWAPcd

explanation:

/..WAP../{                          # for line containt WAP with 2 chars wrap
    wapPosition = index($0,"WAP") - 2;  # find the position of WAP - 2 chars
    output = substr($0, wapPosition, 7);# output is 7 chars length from wapPostion
    print output;                   # print output
}
2
  • Thanks so much; I was able to make that work for my purposes, dragged out only the -2 character and compared with numerals to ensure i only trapped numerals. Thank you again! Jun 11 '19 at 20:55
  • @DanielPatrick rather than finding . and then comparing with [0-9], just look for [0-9] in the first place - /[0-9].WAP/. You know this full-line approach would print 7 if the input was ,x,7,WAP,foo, though, right? Is that what you would want or do you only want to print the digit 2 chars before WAP if it's in the same comma-separated field as WAP?
    – Ed Morton
    Jun 12 '19 at 12:14
0

With GNU Awk, you could use a capture group in the match function and access its content via the optional array parameter:

$ echo ',x,x,x,x,x,xx,Yes,"1 WAP, other stuff, other stuff",no,x' | 
    awk 'match($0,/([0-9]).WAP/,a) {print a[1]}'
1

More portably, you could use a match + substr as

awk 'match($0,/[0-9].WAP/) {print substr($0,RSTART,1)}'

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.