Monday, January 21, 2008

Substitute character by position - SED


This might be useful in situations where you are interested to replace a range of positions in a file with some value/string. Your input will be - line number of the file, character range position, and "replace with" string/value.

e.g:

To replace character position 7-8 with "JK" in 2nd line of out.txt, here is the way using sed:


$ sed -r "2 ~ s/^(.{6})(.{2})/\1JK/" out.txt > out.txt.tmp; mv out.txt.tmp out.txt

Your range was : 7-8
7-1=6
6+2=8

Similar post:
- Replace text based on position using sed

6 comments:

Anonymous said...

In VI editor this can be done i simple way.
:%s/orgText/NewTest/gc enter

gc at the end will ask for conformation, Current or Nexr or All.
Then
:w fileName save the modification in new name. :q! will exit without any change.

Unknown said...

Hi Chinmaya,

First thanks for reading my post.

Well, the one you specified is a "replacing" way in vi, can be done from outside using sed:

sed 's/orgText/NewTest/' file

But if you read the post properly it tells about substitute based on character position range :-)

Unknown said...

Hello Jadu,

For some reason the command you posted doesn't work for AIX implementation. It seems like AIX implementation doesn't understand the -r option of sed.

Unknown said...

Thai,

try "man sed" to see if your AIX version of sed has any options for supporting extended regular expressions (-r). I will post any alternative solution if I find any. Thanks.

//Jadu

rahulsx said...

Hi Jadu,,

I have a file having lines like :
ABCDEFGH12345678QWERT
CVBNMHTY98765432ISDFG

I need to replace the 8 numbers in between ie 9th character to 16th
using the matching :

0 --> H
1 --> W
2 --> E
3 --> V
4 --> T
5 --> M
6 --> F
7 --> B
8 --> Q
9 --> C
in all the lines of the file



Unknown said...

# bash function to implement the change requested
fx() {
# $1 -> filename # file must exist, must be a regular text, readable
# $2 -> line num # line num must be numeric & <= num of lines in input file
# $3 -> start pos # must be numeric
# $4 -> end pos # must be numeric and > start pos
# $5 -> repl # must not chars that meaning to sed on its RHS, e.g., /

case $# in [0-4] ) return;; esac

ifile=$1
linenum=$2
start_pos=$3
end_pos=$4
repl=$5

echo "
ifile=$1
linenum=$2
start_pos=$3
end_pos=$4
repl=$5
"

sed -e "
${linenum}{
s/./&\n/$end_pos
s/./\n&/$start_pos
s/\n.*\n/$repl/
}
" < $ifile
}
# then call it as
fx yourfile 2 7 8 "JK"


As for the problem posed by OP : rahulsx
> I have a file having lines like :
> ABCDEFGH12345678QWERT
> CVBNMHTY98765432ISDFG
>
> I need to replace the 8 numbers in between ie 9th character to 16th
> using the matching :
>
> 0 --> H
> 1 --> W
> 2 --> E
> 3 --> V
> 4 --> T
> 5 --> M
> 6 --> F
> 7 --> B
> 8 --> Q
> 9 --> C
> in all the lines of the file

This is easily doable with "sed" , like as:

sed -e '
s/./&\n/16
s/./\n&/9
h
s/.*\n//;s/\n.*//
y/0123456789/HWEVTMFBQC/
G
s/^\(.*\)\n.*\n\(.*\n.*\)/\1\2/
s/\n//
' < yourfile

© Jadu Saikia www.UNIXCL.com