Nir
Nir

Reputation: 2629

replace string in text based on another match

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.

Upvotes: 1

Views: 101

Answers (4)

RavinderSingh13
RavinderSingh13

Reputation: 133428

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

Upvotes: 1

sseLtaH
sseLtaH

Reputation: 11207

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

Upvotes: 2

DevSolar
DevSolar

Reputation: 70233

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.

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626690

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

Upvotes: 1

Related Questions