Ezzmazz
Ezzmazz

Reputation: 133

How to apply my sed command to some lines of all my files?

I've 95 files that looks like :

2019-10-29-18-00/dev/xx;512.00;0.4;/var/x/xx/xxx
2019-10-29-18-00/dev/xx;512.00;0.68;/xx
2019-10-29-18-00/dev/xx;512.00;1.84;/xx/xx/xx
2019-10-29-18-00/dev/xx;512.00;80.08;/opt/xx/x
2019-10-29-18-00/dev/xx;20480.00;83.44;/var/x/x
2019-10-29-18-00/dev/xx;3584.00;840.43;/var/xx/x
2019-10-30-00-00/dev/xx;2048.00;411.59;/
2019-10-30-00-00/dev/xx;7168.00;6168.09;/usr
2019-10-30-00-00/dev/xx;3072.00;1036.1;/var
2019-10-30-00-00/dev/xx;5120.00;348.72;/tmp
2019-10-30-00-00/dev/xx;20480.00;2033.19;/home
2019-10-30-12-00;/dev/xx;5120.00;348.72;/tmp
2019-10-30-12-00;/dev/hd1;20480.00;2037.62;/home
2019-10-30-12-00;/dev/xx;512.00;0.43;/xx
2019-10-30-12-00;/dev/xx;3584.00;794.39;/xx
2019-10-30-12-00;/dev/xx;512.00;0.4;/var/xx/xx/xx
2019-10-30-12-00;/dev/xx;512.00;0.68;/xx
2019-10-30-12-00;/dev/xx;512.00;1.84;/var/xx/xx
2019-10-30-12-00;/dev/xx;512.00;80.08;/opt/xx/x
2019-10-30-12-00;/dev/xx;20480.00;83.44;/var/xx/xx
2019-10-30-12-00;/dev/x;3584.00;840.43;/var/xx/xx

For some lines I've 2019-10-29-18-00/dev and for some other lines, I've 2019-10-30-12-00;/dev/

I want to add the ; before the /dev/ where it is missing, so for that I use this sed command :

sed 's/\/dev/\;\/dev/'

But How I can apply this command for each lines where the ; is missing ? I try this :

for i in $(cat /home/xxx/xxx/xxx/*.txt | grep -e "00/dev/")
do 
sed 's/\/dev/\;\/dev/' $i > $i
done

But it doesn't work... Can you help me ?

Upvotes: 0

Views: 884

Answers (5)

Rob Pearce
Rob Pearce

Reputation: 1

The easiest way would be to adjust your regex so that it's looking a bit wider than '/dev/', e.g.

sed -i -E 's|([0-9])/dev|\1;/dev|'

(note that I'm taking advantage of sed's flexible approach to delimiters on substitute. Also, -E changes the group syntax)

Alternatively, sed lets you filter which lines it handles:

sed -i '/[0-9]\/dev/ s/\/dev/;/dev/'

This uses the same substitution you already have but only applied on lines that match the filter regex

Upvotes: 0

potong
potong

Reputation: 58420

This might work for you (GNU sed & parallel):

parallel -q sed -i 's#;*/dev#;/dev#' ::: *.txt

or if you prefer:

sed -i 's#;*/dev#;/dev#' *.txt

Upvotes: 1

RavinderSingh13
RavinderSingh13

Reputation: 133518

Could you please try following with GNU awkif you are ok with it.

awk -i inplace '/00\/dev\//{gsub(/00\/dev\//,"/00;/dev/")} 1'  *.txt

sed solution: Tested with GNU sed for few files and it worked fine.

sed -i.bak  '/00\/dev/s/00\/dev/00\;\/dev/g' *.txt

Upvotes: 1

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

grep for filtering can be eliminated in your case, we can accomplish the task with a single sed command:

for f in $(cat /home/xxx/xxx/xxx/*.txt)
do 
    [[ -f "$f" ]] && sed -Ei '/00\/dev/ s/([^;])(\/dev)/\1;\2/' "$f"
done

Upvotes: 0

KamilCuk
KamilCuk

Reputation: 141010

Ignore lines with ;/dev.

sed '/;\/dev/{p;d}; s^/dev^;/dev^'

The /;\/dev/ check if the line has ;/dev. If it has ;/dev do: p - print the current line and d - start from the beginning.

You can use any character with s command in sed. Also, there is no need in escaping \;, just ;.

How I can apply this command for each lines where the ; is missing ? I try this

Don't edit the same file redirecting to the same file $i > $i. Think about it. How can you re-write and read from the same file at the same time? You can't, the resulting file will be in most cases empty, as the > $i will "execute" first making the file empty, then sed $i will start running and it will read an empty file. Use a temporary file sed ... "$i" > temp.txt; mv temp.txt "$i" or use gnu extension -i sed option to edit in place.

What you want to do really is:

grep -l '00/dev/' /home/xxx/xxx/xxx/*.txt |
xargs -n1 sed -i '/;\/dev/{p;d}; s^/dev^;/dev^'

grep -l prints list of files that match the pattern, then xargs for each single one -n1 of the files executes sed which -i edits files in place.

Upvotes: 0

Related Questions