You are not logged in.

#1 2011-11-13 23:31:43

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

sed usage question

The last column of the log file shows the full path to a file and some entries CONTAIN spaces.  I want to use sed to substitute the space to an underscore, BUT I only wanna do it from a particular character to the end of the line.  How can I accomplish this?

Tue Aug 23 20:38:01 2011 /media/data/test file 1.txt
Wed Aug 24 11:30:01 2011 /media/data/test file 2.txt
Fri Aug 26 17:13:01 2011 /media/data/test file 3.txt
Sun Aug 28 17:16:02 2011 /media/data/test file 4.txt

The effect I'm after it convert the about to the following:

Tue Aug 23 20:38:01 2011 /media/data/test_file_1.txt
Wed Aug 24 11:30:01 2011 /media/data/test_file_2.txt
Fri Aug 26 17:13:01 2011 /media/data/test_file_3.txt
Sun Aug 28 17:16:02 2011 /media/data/test_file_4.txt

Tried:

sed '/\// s, ,_,' log

But of course, this will change the very first space to an underscore, not the space and all subsequent spaces AFTER the first forward slash.

Last edited by graysky (2011-11-13 23:32:12)

Offline

#2 2011-11-13 23:39:11

/dev/zero
Member
From: Melbourne, Australia
Registered: 2011-10-20
Posts: 1,247

Re: sed usage question

The fact that you're actually interested in specific fields and not the entire text stream would suggest awk to me.

Offline

#3 2011-11-13 23:43:31

graysky
Wiki Maintainer
From: :wq
Registered: 2008-12-01
Posts: 10,731
Website

Re: sed usage question

I solved my problem with awk, but I still want to know how I can use sed to do it.

awk solution (main reason for wanting to do this was to reorder the date to a standard format which is easily done in awk:

awk '{ print $3"-"$2"-"$5" "$6 $7 $8 $9 $10}' log

Last edited by graysky (2011-11-13 23:44:10)

Offline

#4 2011-11-13 23:46:15

/dev/zero
Member
From: Melbourne, Australia
Registered: 2011-10-20
Posts: 1,247

Re: sed usage question

Remove White Space From Specific Columns In A Text File
How Can I Strip White Space From The Start And End Of Fields Using Awk

Edit: sorry, didn't see your last post before posting.

Last edited by /dev/zero (2011-11-13 23:46:48)

Offline

#5 2011-11-18 21:58:10

zorro
Member
Registered: 2011-11-18
Posts: 47

Re: sed usage question

This may be what you are looking for.

sed 'h; s/[^/]*\///; s/ /_/g; x; s/\/.*/\//; G; s/\n//'

Thanks

Offline

#6 2011-11-18 22:04:07

eldragon
Member
From: Buenos Aires
Registered: 2008-11-18
Posts: 1,029

Re: sed usage question

zorro wrote:

This may be what you are looking for.

sed 'h; s/[^/]*\///; s/ /_/g; x; s/\/.*/\//; G; s/\n//'

Thanks

and thats is why i hate sed. care to explain this crazy language?

Offline

#7 2011-11-18 22:16:21

zorro
Member
Registered: 2011-11-18
Posts: 47

Re: sed usage question

sed 'h; s/[^/]*\///; s/ /_/g; x; s/\/.*/\//; G; s/\n//'

h               copy line to hold space
s/[^/]*\///  delete start of line up to first / in pattern space
s/ /_/g       replace all spaces with underscores
x               exchange hold space and pattern space
s/\/.*/\//     delete from first / to end of line
G              append hold space to pattern
s/\n//         remove auto inserted new line

Offline

#8 2011-11-18 23:25:29

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: sed usage question

Here is another one, it's faster when there are few lines with spaces after the slash, but slower when there are many:

sed ':begin;s/\/.* /&/;T;s/\(\/[^ ]*\) /\1_/;bbegin'

:begin    label
s/\/.* /&/    fake substitution, look for a space after a /
T      if it didn't work, go to end of the script (print, next line)
s/\(\/[^ ]*\) /\1_/      change one space to an underscore
bbegin     move to label begin

Offline

#9 2011-11-19 01:39:26

juster
Forum Fellow
Registered: 2008-10-07
Posts: 195

Re: sed usage question

This works in GNU sed but not BSD seds:

s/ /_/6g

Or there's awk if you're not into the whole brevity thing:

# adding onto graysky's last post
{ printf "%s-%s-%s %s", $3, $2, $5, $6; for(i = 7; i <= NF; i++){ printf "_" $i } print "" }
# or maybe
{ printf "%s-%s-%s ", $3, $2, $5; f = substr($0, 25); gsub(/ /, "_", f); print f }

edit: removed extra brace

Last edited by juster (2011-11-19 01:41:21)

Offline

#10 2011-11-19 16:23:18

N30N
Member
Registered: 2007-04-08
Posts: 273

Re: sed usage question

This is how I'd do it:

sed -r ":loop
s|^([^/]+ /[^ ]+) |\1_|g
t loop"

Offline

#11 2011-11-19 19:39:44

zorro
Member
Registered: 2011-11-18
Posts: 47

Re: sed usage question

This is even smaller.

sed -r ':loop; s|(.*/.*) |\1_|;t loop'

Offline

#12 2011-11-19 22:03:40

N30N
Member
Registered: 2007-04-08
Posts: 273

Re: sed usage question

And so is this:

sed -r ":loop;s|(/.*) |\1_|;t loop"

Offline

Board footer

Powered by FluxBB