Home > Back-end >  How to replace specific values of a string from a file BASH
How to replace specific values of a string from a file BASH

Time:03-15

I'm trying to replace some values from a string into another text, I've made a simplier example with numbers to be more comprehensive. Admitting I've generated a sequence from 1 to 100, I want to replace every numbers divisible by 3 or 5 and replace it by some texts for each case.

'''
#!/bin/bash
# generate a sequence and save it into a file
suite=$(seq -w 1 100)
echo $suite > suite.txt

# printing every multiple of 3 and 5
var3="$(awk -F' ' '{for(i=1;i<=NF;i  )if(!($i%3))print $i}' suite.txt)"
var5="$(awk -F' ' '{for(i=1;i<=NF;i  )if(!($i%5))print $i}' suite.txt)"

# replacing multiple of 3 and 5 by some text 
sed -i 's/$var3/foo/g' suite.txt
sed -i 's/$var5/bar/g' suite.txt
'''

expected result : 001 002 foo 004 bar foo 007 008 foo bar etc.

My sed command doesn't work at all, I'm doing something wrong... Do you have any advise please ?

Thanks for your help Best regards

Golgoth

CodePudding user response:

Look what you are putting in var3:

seq -w 1 100 | awk -F' ' '{for(i=1;i<=NF;i  )if(!($i%3))print $i}'
# or with one field in each line
seq -w 1 100 | awk '$1%3==0 {print $i}'

This is a long string with numbers that you want to replace. When you want to use awk for constructing a sed condition, you need something like seq -w 1 100 | sed -r 's/^(003|006|009|012)$/foo/'. Constructing this line is possible with

var3=$(seq -w 1 100 | awk '$1%3==0 {total=total delim $1; delim="|"} END {print total}')
seq -w 1 100 | sed -r "s/^($var3)$/foo/g"

You don't need the sed script

seq -w 1 100 | awk '{if ($1%3==0) print "foo"; else print $1}'

CodePudding user response:

While we could dynamically generate a series of sed scripts to perform the replacements, one GNU awk idea that may be a bit more straightforward:

awk -v replace="3:foo,5:bar" '                   # <fieldno:replacement> pairs

BEGIN { n=split(replace,arr1,",")                # split our fieldno:replacement pairs into the pairs[] array
        for (i=1;i<=n;i  ) {
            split(arr1[i],arr2,":")
            pairs[arr2[1]]=arr2[2]               # index=fieldno, value=replacement
        }
      }

      { PROCINFO["sorted_in"]="@ind_num_asc"     # apply replacements in fieldno (ascending) order
        for (i in pairs)
            for (j=i 0;j<=NF;j =i)
                $j=pairs[i]                      # replace field #j with current pairs[i] value
      }
1                                                # print current line
' suite.txt

This generates:

001 002 foo 004 bar foo 007 008 foo bar 011 foo 013 014 bar 016 017 foo 019 bar foo 022 023 foo bar 026 foo 028 029 bar 031 032 foo 034 bar foo 037 038 foo bar 041 foo 043 044 bar 046 047 foo 049 bar foo 052 053 foo bar 056 foo 058 059 bar 061 062 foo 064 bar foo 067 068 foo bar 071 foo 073 074 bar 076 077 foo 079 bar foo 082 083 foo bar 086 foo 088 089 bar 091 092 foo 094 bar foo 097 098 foo bar

NOTES:

  • requires GNU awk for PROCINFO["sorted_in"] support
  • for input fields that match multiple replacement criteria (eg, field #15), we apply all criteria to the field with the net result being that the highest numbered pairs[] index (5 in this case) is the final replacement for the field (eg, field #15 replaced with pairs[5]=bar)
  • Related