commando
commando

Reputation: 3

Replace specific columns in fixed width files using sed

I have this string in my data file (dat.txt) =>

00000
10101

I want to replace the 1st row, second and fourth column, I tried this:

$>sed -i "/^1/s/0/1/2" dat.txt
$>sed -i "/^1/s/0/1/4" dat.txt

But when I reload the dat.txt, it does not change anything. Is my command wrong?

Upvotes: 0

Views: 4004

Answers (4)

Dennis Williamson
Dennis Williamson

Reputation: 359965

Try this:

sed -i '1{s/./1/2;s/./1/4}' dat.txt

Result:

01010
10101

Upvotes: 2

paxdiablo
paxdiablo

Reputation: 881263

For a start, unless that first line is your zeroth row, you'll be changing the second (the one that begins with 1).

And that 2 and 4 don't change the second/fourth column, they change the second/fourth occurrence of the search pattern.

See the following transcript:

$ cat dat.txt
00000
10101

$ sed -i "/^1/s/0/1/2" dat.txt ; cat dat.txt
00000
10111

$ sed -i "/^1/s/0/1/4" dat.txt ; cat dat.txt
00000
10111

You can see that the first sed changed the second occurrence of 0 to 1, and that was in the fourth column. The second sed changed nothing since you asked it to do it to the fourth occurrence and there aren't four 0 characters there.

If you want to change specific columns, you can use capturing patterns, as in the following transcript:

$ cat dat.txt
00000
10101

$ sed -i "/^1/s/^\(.\)0/\11/" dat.txt ; cat dat.txt
00000
11101

$ sed -i "/^1/s/^\(...\)0/\11/" dat.txt ; cat dat.txt
00000
11111

The parentheses capture the pattern so that \1 in the replacement text can be used to refer to that captured text. Because you're talking about a small number of characters before the one you want to change, you can use ... as a pattern. If you wanted to change (for example) the 85th column, you'd probably be better off with something like:

sed -i "/^1/s/^\(.\{84\}\)0/\11/" dat.txt ; cat dat.txt

Upvotes: 1

icyrock.com
icyrock.com

Reputation: 28598

This should do it:

sed -i -e '1 s/0/1/2' -e '1 s/0/1/3' dat.txt

-e means add a command, so they execute one after another. You can also use this:

sed -i '1 s/0/1/2; 1 s/0/1/3' dat.txt

Note that, in your question, /^1/ part before s command to sed means: change all rows that begin (^ means 'match start of the line') with 1. Look here:

in particular the section the link points to (Restricting to a line number) and the next (Patterns) section.

Upvotes: 0

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798546

The number after the substitution is the number of the instance to change, not the specific character. There is no fourth instance so the second has no effect, whereas the first should change the second line to 10111.

Upvotes: 1

Related Questions