Home > Enterprise >  replace string in text based on another match
replace string in text based on another match

Time:10-06

So I have this file

a chair x 0 y
a table x 0 y
a window x 0 y
a computer x 0 y

I want to replace the 0 value with 111 value for the rows that have window in them. So the output will look like:

a chair x 0 y
a table x 0 y
a window x 111 y
a computer x 0 y

Running sed 's/window.*0/y/' a.txt does not give me what I want.

CodePudding user response:

sed "s/ window \(.\) 0 / window \1 111 /"

Parenthesis (which need to be escaped) "group" a match. You can refer to groups by sequential number in your replacement string, preserving the matched value.

As it is unclear what your "a" / "x"/ "y" could stand in for (are they always "a"/"x"/"y", or always a single lowercase letter, or...), I can't really give you an "optimal" sed line. If this is to be release-quality code, you need to make sure there can be no "false positives" (i.e. if "window" can appear at some other place than the second column). You could use the grouping mechanics I showed above to match the whole line, ensuring that "window" is in the second column... which could get hairy if a column could conceivably contain spaces. As I said, not enough information.

CodePudding user response:

You can use the following GNU sed solution:

sed -i -E 's/^(\S \s window\s \S \s )0(\s)/\1111\2/' a.txt

Here,

  • ^ - start of string
  • (\S \s window\s \S \s ) - Group 1 (\1): one or more non-whitespaces, one or more whitespaces, window text, one or more whitespaces, one or more non-whitespaces and one or more whitespaces
  • 0 - a 0 char
  • (\s) - Group 2 (\2): a whitespace

See the online demo:

#!/bin/bash
s='a chair x 0 y
a table x 0 y
a window x 0 y
a computer x 0 y'

sed -E 's/^(\S \s window\s \S \s )0(\s)/\1111\2/'  <<< "$s"

Or, you can use awk:

awk '$2 == "window" && $4 == "0"{$4=111}1' a.txt > a.txt.tmp && mv -f a.txt.tmp a.txt

It means, if Field 2 is window and Field 4 is 0, replace the fourth field with 111.

See the online demo:

#!/bin/bash
s='a chair x 0 y
a table x 0 y
a window x 0 y
a computer x 0 y'

awk '$2 == "window" && $4 == "0"{$4=111}1'  <<< "$s"

Output:

a chair x 0 y
a table x 0 y
a window x 111 y
a computer x 0 y

CodePudding user response:

Using sed

$ sed '/window/I{s/0/111/}' input_file
a chair x 0 y
a table x 0 y
a window x 111 y
a computer x 0 y

CodePudding user response:

Since you specifically asked for sed. With your shown samples please try following sed code. Here is the Online Demo for used regex in sed code.

sed -E '/window/s/^([^[:space:]] [[:space:]] [^[:space:]] [[:space:]] [^[:space:]] [[:space:]] )[^[:space:]] (.*)$/\1111\2/'  Input_file

OR To make sure that string window is coming in 2nd field/column then try following.

sed -E '/^[^[:space:]] [[:space:]] window[[:space:]] /s/^([^[:space:]] [[:space:]] [^[:space:]] [[:space:]] [^[:space:]] [[:space:]] )[^[:space:]] (.*)$/\1111\2/' Input_file

Output will be as follows:

a chair x 0 y
a table x 0 y
a window x 111 y
a computer x 0 y
  • Related