dongK
dongK

Reputation: 51

grep a specific string and replace the file with sed

I need some solution to replace some string. I Have a "file" with this on the content:

23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97.9560, 2016-08-25 16:06:49
23713, System Free Space, OK, 88.0078, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63.2227, 2016-09-21 10:57:03

I used this code to take "Free" value on it like this:

 grep Free file.txt |grep OK | cut -d K -f 2 |cut -d , -f 2 |cut -d . -f 1

Then i got this result:

97
88
63

I need to insert "%" into the result using this code:

 grep Free rs.txt |grep OK | cut -d K -f 2 |cut -d , -f 2 |cut -d . -f 1 |sed 's/$/%/g'

The result like this:

97%
88%
63%

My question is, how to replace the value on the file for example "97.9560" with new result "97%" etc.
Kindly give me an advice. Thanks

Upvotes: 2

Views: 79

Answers (3)

Sundeep
Sundeep

Reputation: 23697

Couple of perl solution

$ perl -pe 's/OK,\s*\d+\K\.\d+/%/ if /Free/' ip.txt
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03
  • OK,\s*\d+\K positive lookbehind, OK, followed by zero or more spaces and one or more digits
  • \.\d+ dot followed by one or more digits
  • replacement text is %, applied only when input line contains Free

Another way is to split input line on , and change 4th field

perl -F, -le '$F[3] =~ s/\.\d+/%/ if /Free/; print join",", @F' ip.txt 

If result is as expected, changes can be done inplace with

perl -i no backup

or

perl -i.bkp with backup

Upvotes: 0

P....
P....

Reputation: 18411

Here is awk version solution:

awk -v OFS=, -F, '/Free.*OK/ {split($4,a,"."); $4=a[1]"%"}1' infile
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03

Explanation :

this awk command will take actions on only those lines which contains Free followed by OK. As this file is a csv file, get the 4th field and split into two parts separated by . . print the part which is of interest after appending % sign to it.

sed is best suited for find and replace tasks as it support in-place replacement. However it can be achieved through awk using following way :

awk -v OFS=, -F, '/Free.*OK/ {split($4,a,"."); $4=a[1]"%"}1' infile > infile.tmp && mv infile.tmp infile

Upvotes: 1

John1024
John1024

Reputation: 113984

To replace the value in the file:

sed -E -i.bak 's/(Free.*OK,[^.]*)[.][^,]*/\1%/' file.txt

Example:

$ sed -E -i.bak 's/(Free.*OK,[^.]*)[.][^,]*/\1%/' file.txt
$ cat file.txt
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03

How it works

  • -E

    This tells sed to use extended regular expressions. This reduces the number of backslashes that we need.

  • -i.bak

    This tells to change the file in-place, leaving a back-up file.

  • s/(Free.*OK,[^.]*)[.][^,]*/\1%/

    This tells sed to make the substitution that you need. In this case, sed looks for text matching the regex (Free.*OK,[^.]*)[.][^,]*. This matches Free followed by OK, followed by anything except a period, followed by a period, followed by anything except a comma. The parentheses cause everything from Free to the last character before the period to be saved in group 1.

    The text that was matched is replace by \1% which means the text belonging to group 1, \1, followed by a percent sign, %.

Upvotes: 2

Related Questions