开发者

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开发者_JAVA百科 dat.txt, it does not change anything. Is my command wrong?


Try this:

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

Result:

01010
10101


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


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.


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:

  • http://www.grymoire.com/Unix/Sed.html#uh-26

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜