2

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

2
  • 1
    I don't know what sed supports when it concerns the few 'advanced' regex syntax, but with PCRE, you can do it like that. Commented Oct 10, 2013 at 18:57
  • Sed don't have PCRE, but that is a interesting site! thanks! Commented Oct 10, 2013 at 19:04

5 Answers 5

1

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this works and uses sed!! i had tried to inserting newlines to break the log, but in my attempt i required several sed commands and didn't feel right. Your solution is looks perfect!
1

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

2 Comments

that }1 is unknown for me... can you explain it, or point me to some doc? i don't know even how to search for that in google!! :) i can see it prints the line, but changing the number to other than 0 does the same thing.
1 does mean print any line. Its always true, so it will do the default action, print. It could be written like this 1 {print $0}. So this awkwill change value of filed $2, when its machine, and then the 1 does print all lines, including the modified lines.
0

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.