简体   繁体   中英

Replace character in a string using awk or sed

Given the string below, how can I replace 6th and 7th by getting 14th and 15th digit using awk or sed.

xxxxx02xxxxxx89xx
xxxxx22xxxxxx33xx

output

xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx

I am newbie here, sorry for my question.

The sed command is straightforward, but hard to read:

sed 's/\(.....\)..\(......\)\(..\)/\1\3\2\3/'

A possibly more maintainable solution can be had with Gnu awk (but not other awk varieties. However, see below.):

gawk -v FIELDWIDTHS="5 2 6 2 999" -v OFS='' '{$2=$4;print}'

The FIELDWIDTHS variable defines 5 fixed-width fields: the first 5 characters, the next two characters (positions 6 and 7); the next six characters (8 through 13); the next two characters (14 and 15); and the next (up to) 999 characters, which should be the rest of the line. (If you have longer lines, increase as necessary). Setting OFS to empty is often useful with fixed-length fields; it prevents awk from inserting spaces between fields in the output.

FIELDWIDTHS is a GNU awk extension. However, it is easy enough to reimplement in Posix awk . Here's a simple implementation:

function fieldwidth_set(         i) {
  if (PROCINFO["FS"]) FIELDWIDTHS = FIELDWIDTHS;
  else if (length(FIELDWIDTHS)) {
    _FW_NF = split(FIELDWIDTHS, _FW_ARRAY);
    for (i in _FW_ARRAY) {
      if (_FW_ARRAY[i] !~ /^[0-9]+$/) {
        printf "Illegal value '%s' in FIELDWIDTHS\n", _FW_ARRAY[i] >>"/dev/stderr";
        exit 1;
      }
      _FW_ARRAY[i]+=0;
    }
  } else
    _FW_NF = 0;
}
function set_fieldwidth(fw) { FIELDWIDTHS=fw; fieldwidth_set(); }
function fw_(               a,i,k) {
  if (_FW_NF) {
    a = $0;
    $0 = "";
    k=1;
    for (i=1; i<=_FW_NF; ++i) { 
      $i = substr(a, k, _FW_ARRAY[i]);
      k+=_FW_ARRAY[i];
    }
  }
}
BEGIN{set_fieldwidth()}
{fw_()}

As far as I know, only Gnu awk lets you mix program files and program text on the awk command-line. Posix requires the -f program-file option, which may be repeated, but does not require the -e program-text option as implemented by Gnu awk. Consequently, if you want to use the above snippet with a command-line awk program, you need to do something like this:

awk -v FIELDWIDTHS="5 2 6 2 999" -v OFS= -f fw.awk -f <(echo '{$2=$4;print}')

(Assuming you put the fieldwidth snippet into fw.awk .)

For efficiency, fw.awk insists that you tell it that you've changed FIELDWIDTHS by calling fieldwidth_set() . Or you can use set_fieldwidth("....") to set FIELDWIDTHS to a new value. It will work with GNU awk as well as with other awk implementations; it lets GNU awk do the heavy lifting.

You could try the below sed command,

$ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})(..)(.{6})../\1\2\3\2/g' 
xxxxx03xxxxxx03xx
$ echo 'xxxxx03xxxxxx75xx' | sed  's/^\(.\{5\}\)\(..\)\(.\{6\}\)../\1\2\3\2/g'
xxxxx03xxxxxx03xx

It replaces 14th and 15th digits with the digits in the position 6 and 7th.

$ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})..(.{6})(..)/\1\3\2\3/g'
xxxxx75xxxxxx75xx
$ echo 'xxxxx03xxxxxx75xx' | sed 's/^\(.\{5\}\)..\(.\{6\}\)\(..\)/\1\3\2\3/g'
xxxxx75xxxxxx75xx

It replaces 6th and 7th digits with the digits in the position 14th and 15th.

This should follow your request and work with all awk :

awk '{$6=$14;$7=$15}1' FS= OFS= file
xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx

It will change the digit in position 6 by the one in 14 and the one in 7 with the one int 15

If FS="" does not work, try this:

awk '{n=split($0,a,"");a[6]=a[14];a[7]=a[15];for (i=1;i<=n;i++) printf "%s",a[i];print ""}' input

As request in one of the comment:
It works, thanks! How about if I want to replace 14th and 15th digit by 6th and 7th digit? – Vision111

awk '{$14=$6;$15=$7}1' FS= OFS= file

This will work without GNU awk GAWK

awk 'sub(/[0-9]+/,substr($0,14,2))' file

Or longer but more generic

awk '{print substr($0,0,5) substr($0,14,2) substr($0,8)}' file

RESULT:

xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM