I have the following table:
cat test.txt
c_az_1858 2020-01-15 -5.50 Parking Serv Parking Serv
c_az_1859 2020-01-15 -80.56 Avery Johnson Avery Johnso 592242
c_az_1860 2020-01-15 100.00 Wayne Alexander Flin 7 Pikarere S Titahi Bay
c_az_1861 2020-01-15 51.75 Setefano P M Crew Cuts Lawns
c_az_1862 2020-01-13 -5.50 Parking Serv Parking Serv
c_az_1863 2020-01-13 -3.00 Parking Serv Parking Serv
c_az_1864 2020-01-13 57.50 0520/5200000000/002 Apu Cresent
c_az_1865 2020-01-13 46.00 Becta Ltd Taylormallon Lawns
c_az_1866 2020-01-13 28.75 Strata Title Adminis Crewcut Gard De Payment
c_az_1867 2020-01-13 19.17 D S & S A Tapp David Tapp Weekly Lawn
I am trying to run a series of search patterns against the file so it prints out the search pattern that calls the line in front of the line. The search pattern scans column $4. Like so:
Park: c_az_1858 2020-01-15 -5.50 Parking Serv Parking Serv
ayn : c_az_1860 2020-01-15 100.00 Wayne Alexander Flin 7 Pikarere S Titahi Bay
o P: c_az_1861 2020-01-15 51.75 Setefano P M Crew Cuts Lawns
Park: c_az_1862 2020-01-13 -5.50 Parking Serv Parking Serv
Park: c_az_1863 2020-01-13 -3.00 Parking Serv Parking Serv
S A: c_az_1867 2020-01-13 19.17 D S & S A Tapp David Tapp Weekly Lawn
To this end I have written the following script:
#!/usr/bin/env bash
awk '
BEGIN{
FS = OFS = "\t"
x="ayn|o P|S A|Park"
}
{
for (i in x) {
if ($4 ~ i) {
print x[i] ": " , i
}
}
}
' test.txt
When I run this I get the following error message:
awk: cmd. line:7: (FILENAME=test.txt FNR=1) fatal: attempt to use scalar `x' as an array
How is x a scalar and how would this have to be rewritten so it work. Help is much appreciated.
>Solution :
In the current code the following assigns a string to the variable x:
x="ayn|o P|S A|Park"
Assigning these patterns to an array could be done individually like such:
# assign as array values
x[1]="ayn" ; x[2]="o P" ; x[3]="S A" ; x[4]="Park"
# assign as array indices (no need to assign a value)
x["ayn"] ; x["o P"] ; x["S A"] ; x["Park"]
If supplied as a delimited string we can use the split() function to break the values into separate strings and assign them as array values.
Making some changes to OP’s current code:
- allow search patterns to be fed from the shell into an
awkvariable - split the search patterns into individual array components
The modified code:
patterns='ayn|o P|S A|Park'
awk -v ptns="${patterns}" '
BEGIN { FS = OFS = "\t"
split(ptns,arr,"|") # split ptns into array arr[] based on "|" delimiter
for (i in arr)
x[arr[i]] # convert arr[] values to x[] indices
}
{ for (i in x)
if ($4 ~ i) # compare $4 with the array indices
print i ": " $0
}
' test.txt
Or we can just use the results of the split() and make sure we match $4 with the value in the array (as opposed to the index of the array), eg:
patterns='ayn|o P|S A|Park'
awk -v ptns="${patterns}" '
BEGIN { FS = OFS = "\t"
split(ptns,arr,"|") # split ptns into array arr[] based on "|" delimiter
}
{ for (i in arr)
if ($4 ~ arr[i]) # compare $4 with the array values
print arr[i] ": " $0
}
' test.txt
Both of these generate:
Park: c_az_1858 2020-01-15 -5.50 Parking Serv Parking Serv
ayn: c_az_1860 2020-01-15 100.00 Wayne Alexander Flin 7 Pikarere S Titahi Bay
o P: c_az_1861 2020-01-15 51.75 Setefano P M Crew Cuts Lawns
Park: c_az_1862 2020-01-13 -5.50 Parking Serv Parking Serv
Park: c_az_1863 2020-01-13 -3.00 Parking Serv Parking Serv
S A: c_az_1867 2020-01-13 19.17 D S & S A Tapp David Tapp Weekly Lawn