Reputation: 449
How can I find and replace value for particular column using awk
?
Say for example -> I have a file test having the content:
"abc":"100"::"new"
"xyz":"200":"mob":"old"
"lmn":"300"::"new"
"pqr":"400":"mob2":"new"
Now, if 3rd column is blank then I want to replace the blank value from "N/A"
otherwise print the line as it is, so that the output would be like:
"abc":"100":"N/A":"new"
"xyz":"200":"mob":"old"
"lmn":"300":"N/A":"new"
"pqr":"400":"mob2":"new"
Although I got the output using awk through below command:
awk -F":" '{
if ( $3 == "")
print $1":"$2":\"N\/A\":"$4
else
print $0
}' test
But here I am using the hard coded values for each column like $1
, $2
, so if the blank column changes in other example from 3rd to xyz then have to change the same in command again. Is there any other way to get the same output using awk and without using hard coded values for columns? Thanks for your help.
Upvotes: 2
Views: 8913
Reputation: 22366
First, let's simplifiy your present program a bit:
awk -F: 'BEGIN {OFS=FS} {
if ( $3 == "") $3="N/A"
print $0
}' test
Now we can make two things variable: The column to test, and the replacement string. Hence, the body of the program will look something like
if ( $fieldnumber == "" ) $fieldnumber=replacement
What remains to be done, is to fill in the variables. If you look at the man page of awk, you see that the option -v
allows us to specify the initial value for an awk variable.
awk -F: -v fieldnumber=... -v replacement=...
This allows you to fill this variable from wherever you like - parameter of your shell script, environment variable etc.
UPDATE: Fix output field separator (OFS) UPDATE: Fix syntax error
Upvotes: 3
Reputation: 204731
The right way to do this, using GNU awk for FPAT and a modified input file to demonstrate that it works even when colons are present within quoted fields:
$ cat tst.awk
BEGIN {
FPAT = "([^:]*)|(\"[^\"]+\")"
OFS = ":"
}
$3 == "" { $3 = "\"N/A\"" }
{ print }
$ cat file
"abc:def":"100"::"new"
"xyz":"200":"mob":"old"
"lmn":"123:456:300"::"new"
"pqr":"400":"mob2":"new"
"stu":"600":"foo::bar":"more"
$ awk -f tst.awk file
"abc:def":"100":"N/A":"new"
"xyz":"200":"mob":"old"
"lmn":"123:456:300":"N/A":"new"
"pqr":"400":"mob2":"new"
"stu":"600":"foo::bar":"more"
Upvotes: 2
Reputation: 369
How about below piece of gawk code:
BEGIN {
FS=":"
OFS=":"
}
{
for(i=1; i<=4; i++) {
if ($(i) == "") field[i] = "N/A"
else field[i] = $(i)
}
if ($0 != "") print field[1],field[2],field[3],field[4]
}
-- Or --
Maybe below piece of bash script is much simpler:
#!/bin/bash
export IFS=":"
while read a b c d; do
echo "${a:-N/A}:${b:-N/A}:${c:-N/A}:${d:-N/A}"
done
with input redirection, i.e. this_bash_script.sh < your_test_input.txt
Upvotes: 0
Reputation: 13259
Using GNU awk:
awk -v RS='[:\n]' '!NF{$0="\"N/A\""}{printf "%s%s",$0,RT}' test
The record separator RS
is set to capture the data between the semi-colon :
.
If there isn't any field (!NF
), then set the want string.
The printf statement write the data and the record separator RT
for the current record.
Upvotes: 0