Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

awk sub with a capturing group into the replacement

Tags:

regex

unix

awk

I am writing an awk oneliner for this purpose:

file1:

1   apple
2   orange
4   pear

file2:

1/4/2/1

desired output: apple/pear/orange/apple

addendum: Missing numbers should be best kept unchanged 1/4/2/3 = apple/pear/orange/3 to prevent loss of info.

Methodology:

  1. Build an associative array key[$1] = $2 for file1
  2. capture all characters between the slashes and replace them by matching to the key of associative array eg key[4] = pear

Tried:

gawk 'NR==FNR { key[$1] = $2 }; NR>FNR { r = gensub(/(\w+)/, "key[\\1]" , "g"); print r}' file1.txt file2.txt

#gawk because need to use \w+ regex
#gensub used because need to use a capturing group

Unfortunately, results are 1/4/2/1

key[1]/key[4]/key[2]/key[1]

Any suggestions? Thank you.

like image 583
Harry Avatar asked Nov 29 '22 20:11

Harry


2 Answers

You may use this awk:

awk -v OFS='/' 'NR==FNR {key[$1] = $2; next}
{for (i=1; i<=NF; ++i) if ($i in key) $i = key[$i]} 1' file1 FS='/' file2

apple/pear/orange/apple

Note that if numbers from file2 don't exist in key array then it will make those fields empty.

file1 FS='/' file2 will keep default field separators for file1 but will use / as field separator while reading file2.

like image 92
anubhava Avatar answered Dec 04 '22 04:12

anubhava


EDIT: In case you don't have a match in file2 from file and you want to keep original value as it is then try following:

awk '
FNR==NR{
  arr[$1]=$2
  next
}
{
  val=""
  for(i=1;i<=NF;i++){
    val=(val=="" ? "" : val FS) (($i in arr)?arr[$i]:$i)
  }
  print val
}
' file1 FS="/" file2


With your shown samples please try following.

awk '
FNR==NR{
  arr[$1]=$2
  next
}
{
  val=""
  for(i=1;i<=NF;i++){
    val = (val=="" ? "" : val FS) arr[$i]
  }
  print val
}
' file1 FS="/" file2

Explanation: Reading Input_file1 first and creating array arr with index of 1st field and value of 2nd field then setting field separator as / and traversing through each field os file2 and saving its value in val; printing it at last for each line.

like image 45
RavinderSingh13 Avatar answered Dec 04 '22 05:12

RavinderSingh13