2
h -t 9.641909323 -s 0 -d 29 -p cbr -e 1078 -c 2 -a 0 -i 169 -k MAC
r -t 9.650534114 -s 29 -d 29 -p cbr -e 1020 -c 2 -a 0 -i 169 -k MAC
+ -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC 
- -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
h -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC

here i need to search -s 0 -d 29 -p cbr if its match with any line on that line replace initial h with d

Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73
Naveen.S
  • 730
  • 5
  • 21

7 Answers7

4

With Tcl, you'd write a somewhat longer program than in those other languages:

# Open the files for streaming...
set filename "whatever.log"
set fin [open $filename]
set fout [file tempfile tempName]

# Process the lines, one by one...
while {[gets $fin line] >= 0} {   ### <<< THIS IS IDIOMATIC FOR STREAMING
    if {[string first "-s 0 -d 29 -p cbr" $line]} {
        regsub "^h" $line "d" line
    }
    puts $fout $line
}

# Finalize everything
close $fin
close $fout
file rename $tempName $filename

If you want the output to go to a different file, you can just use:

set fout [open "differentFile.txt" "w"]

instead of the set fout [file tempfile tempName] and omit the file rename. (That will also make the code work on all versions of Tcl earlier than 8.6; file tempfile is a new feature, but everything else used here has been around for ages.)


Alternatively, for a version that reads in all the lines at once, replace the central processing loop with this one-liner that uses line-mode RE substitution and a little bit of smartness:

# Use [puts -nonewline] because the last newline is kept with [read]
puts -nonewline $fout [regsub -all -line "^h(.*-s 0 -d 29 -p cbr)" [read $fin] "d\\1"]

This will, however, hold all the data in memory at once.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • 1
    BTW, for 10k of lines with those sorts of line lengths, I'd do it all in memory. It's less than a MB of data, and we've all got computers with multiple GB of physical RAM… – Donal Fellows May 23 '13 at 07:54
3

If the line matches the pattern and the first field is h set the first field to d:

$ awk '/-s 0 -d 29 -p cbr/&&$1=="h"{$1="d"}1' file
d -t 9.641909323 -s 0 -d 29 -p cbr -e 1078 -c 2 -a 0 -i 169 -k MAC
r -t 9.650534114 -s 29 -d 29 -p cbr -e 1020 -c 2 -a 0 -i 169 -k MAC
+ -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
- -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
h -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC

Edit:

Only replace the first match:

$ awk '/-s 0 -d 29 -p cbr/&&$1=="h"&&!f{$1="d";f=1}1' file
d -t 9.641909323 -s 0 -d 29 -p cbr -e 1078 -c 2 -a 0 -i 169 -k MAC
r -t 9.650534114 -s 29 -d 29 -p cbr -e 1020 -c 2 -a 0 -i 169 -k MAC
+ -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
- -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
h -t 9.650544114 -s 29 -d -1 -p ACK -e 38 -c 2 -a 0 -i 0 -k MAC
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
2

try below sed one-liner:

sed '/-s 0 -d 29 -p cbr/s/^h/d/' file
Kent
  • 189,393
  • 32
  • 233
  • 301
  • Sorry for the noob question but : How come your code line has colors and not mine? (same line...) – xShirase May 22 '13 at 12:03
  • 1
    @xShirase Because you mentioned in answer, you are not sure if it will work. :D just kidding. I don't know how does SO do the code highlighting. but the difference is, I have another part after the quoted segment, which is the input file. yours doesn't. That might be a condition for SO to highlight syntax? – Kent May 22 '13 at 12:08
  • it seems that the code gets highlighted when you use the 4space indentation, but not when you use the backquotes. Further research shows it won't highlight backquoted code even if indented. Thanks ^^ – xShirase May 22 '13 at 12:11
  • Oh I didn't notice it at all. good to know. I write/edit my post in vim, vim does indentation for me. I just pressed `Tab` – Kent May 22 '13 at 12:14
0

Quick answer, I can't test here, something like :

sed '/-s 0 -d 29 -p cbr/s/^h/d/' 

should work. Let me know or edit. I'll be able to check only later. Good luck!

xShirase
  • 11,975
  • 4
  • 53
  • 85
0

You can try with this,

sed  '/-s 0 -d 29 -p cbr/{s/^h\(.*\)/d\1/g}' file
sat
  • 14,589
  • 7
  • 46
  • 65
0

By initial h, you seem to refer to the first character in the matching line. By that assumption, the following should work:

grep -- "-s 0 -d 29 -p cbr" inputfile | sed 's/^h/d/'
devnull
  • 118,548
  • 33
  • 236
  • 227
  • thanks its replace correctly and displayed but my inputfile didn't change. – Naveen.S May 22 '13 at 12:08
  • This wasn't supposed to change the input file. Was it? Try something like: `cp inputfile tmpfile && grep -- "-s 0 -d 29 -p cbr" tmpfile | sed 's/^h/d/' > inputfile` – devnull May 22 '13 at 12:11
0

This might work for you (GNU sed):

sed -r 's/^h(.*-s 0 -d 29 -p cbr)/d\1/' file
potong
  • 55,640
  • 6
  • 51
  • 83