Naveen.S
Naveen.S

Reputation: 750

search a string in a files if it match replace another string in the same line with some string

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

Upvotes: 2

Views: 1526

Answers (7)

potong
potong

Reputation: 58438

This might work for you (GNU sed):

sed -r 's/^h(.*-s 0 -d 29 -p cbr)/d\1/' file

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137627

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.

Upvotes: 4

Chris Seymour
Chris Seymour

Reputation: 85815

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

Upvotes: 3

xShirase
xShirase

Reputation: 12399

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!

Upvotes: 0

Kent
Kent

Reputation: 195129

try below sed one-liner:

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

Upvotes: 2

devnull
devnull

Reputation: 123568

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/'

Upvotes: 0

sat
sat

Reputation: 14949

You can try with this,

sed  '/-s 0 -d 29 -p cbr/{s/^h\(.*\)/d\1/g}' file

Upvotes: 0

Related Questions