Replace | character between the records with a val

2019-07-31 10:43发布

问题:

This is my file.

NAME|NUM|ADDR|AGE
abcd|02|abc|cd|12
jake|04|xy|zzb|12
 lau|92||xcx| 56

My desired output has to be like this

 NAME|NUM|ADDR|AGE
 abcd|02|abc#cd|12
 jake|04|xy#zzb|18 
  lau|92|#xcx| 56

My file had 4 fields and the 3rd col has a pipe delimiter in between the characters like "ice|cream", my requirement is to replace the | field in the 3rd with any value like (#,* or anything). Since this is pipe delimited file i'm unable to replace that particular part of the file exclusively.Any help will be very useful for me..thanks

回答1:

awk solution:

awk -F'|' 'NR==1;NR>1 && NF>4{ print $1,$2,$3"#"$4,$5 }' OFS='|' file
  • NR==1; - print the 1st record as is

  • NR>1 && NF>4 - check if record has excessive fields

  • $3"#"$4 - implode the 3rd and 4th fields replacing separator with a new char #

The output:

NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
 lau|92|#xcx| 56


回答2:

Just set n to the number of whichever field you want to combine with the field after it:

$ cat tst.awk
BEGIN { FS=OFS="|" }
NR==1 { print; next }
{
    for (i=1;i<=NF;i++) {
        sep = (i==n ? "#" : OFS)
        printf "%s%s", $i, (i<NF ? sep : ORS)
    }
}

$ awk -v n=3 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
 lau|92|#xcx| 56

$ awk -v n=2 -f tst.awk file
NAME|NUM|ADDR|AGE
abcd|02#abc|cd|12
jake|04#xy|zzb|12
 lau|92#|xcx| 56


回答3:

Or if you want a more traditional logic based solution, (and admittedly painfully long-handed ;-/) here is another solution

awk -F\| 'BEGIN{OFS="|"}
  {
    #dbg print "#dbg:NF="NF;

    # if this record has an extra character
    if (NF>4){
      # loop over all fields
      for(i=1;i<=NF;i++){
        # if not the field of interest or last field on line, just print it
        if(i!=3 && i!=NF){
          printf("%s|",$i)
        }
        # else this is the problem field, add the # char
        else if (i==3){
          printf $3"#"
        }
        # else if last field on line, add LF char at end
        else if (i==NF){
          printf ("%s\n",$i)
       }
      }
    }
    # record has correct number of FS chars
    else {
      print $0
    }
  }' dat.txt

output

NAME|NUM|ADDR|AGE
abcd|02|abc#cd|12
jake|04|xy#zzb|12
 lau|92|#xcx| 56

I've added comments to code to explain what is going on.


Here it is as a the all-important one-liner ;->

awk -F\| '{if (NF>4){for(i=1;i<=NF;i++){if(i!=3 && i!=NF){printf("%s|",$i)}else if(i==3){printf $3"#"}else if(i==NF){printf ("%s\n",$i)}}}else{print $0}}' dat.txt

IHTH



标签: shell unix awk sed vi