higuita
higuita

Reputation: 2315

Using sed to replace only inside a regexp substring

I have a log where i want to apply a replace just inside a regexp match text.

Example, take this log line:

date machine  text random text and yet more random text - status code

i want o replace the all spaces by a _ inside the text area, without replacing all other spaces in the log. the output would be this:

date machine  text_random_text_and_yet_more_random_text - status code

To match the area i want to replace i have this regexp:

/machine \(.*\) - /

As the text is not standard, i can have one space to 20, so its hard to match it directly, so i match the start and the end of the substring.

Trying to use it i tried this:

sed `/machine \(.*\) - /   s/ /_/g '  logfile

but of course, it will replace all spaces in the log, not just the matched substring.

I managed to do it with awk, by iterating and printing each field until i find the machine, where i change the OFS="_" and restore it to space when i find the -. It works... yet, i was curious if this is possible to solve using sed.

Thanks

Upvotes: 2

Views: 491

Answers (5)

Jotne
Jotne

Reputation: 41446

Since there are two space before text you like to have with underscore and space - space after, you can do like this:

awk -F "  | - " '/machine/ {gsub(/ /,"_",$2)}1' file
date machine text_random_text_and_yet_more_random_text status code

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246744

Perl:

echo "date machine  text random text and yet more random text - status code" | 
perl -pe 's/(?<=machine  )(.*)(?= - )/ ($repl = $1) =~ s{\s}{_}g; $repl /e'
date machine  text_random_text_and_yet_more_random_text - status code

Upvotes: 0

potong
potong

Reputation: 58351

This might work for you (GNU sed):

sed -r 's/(\S+\s+){2}/&\n/;s/\s+-/\n&/;h;y/ /_/;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/' file

Upvotes: 1

Zsolt Botykai
Zsolt Botykai

Reputation: 51593

Another awk solution might be:

awk '{
    # Capture the stringpart in `a`rray
    match($0,"machine  (.*) -",a)
    # Make the changes
    gsub(" ","_",a[1])
    print gensub("machine (.*) -","machine  " a[1] " -","g")
}' INPUTFILE

Upvotes: 0

anubhava
anubhava

Reputation: 784908

Here is one gnu-awk command to solve this:

s='date machine text random text and yet more random text - status code'
awk '{gsub(/ /, "_", $2); print $1 " machine " $2 " - " $3}' FS='machine *| *- *' <<<"$s"

date machine  text_random_text_and_yet_more_random_text - status code

Upvotes: 0

Related Questions