String exception in regex matching for sed handling

I need to match this for substitute command:

whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever 

I'm trying to:

 sed -e 's/__\(.*\)__/\{{\1}}/g' myfile 

But it looks to match __MATCH_THIS__whateverwhatever__AND_THIS__ , creating:

 whatever{{MATCH_THIS__whateverwhatever__AND_THIS}}whateverwhatever 

But I wanted:

 whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever 

How can I specify the line to exclude in the corresponding part? I know how to exclude one character (for example, [^a] ), but not how to exclude a string.

+4
source share
6 answers

You do not need a greedy regular expression, but unfortunately sed does not allow this. However, this can be done in perl.

 perl -pe 's|__(.*?)__|{{$1}}|g' <myfile 

The question mark after the asterisk means that the match is inanimate, so instead of taking the longest match string that he can find, he will take the shortest.

Hope this helps.

If you want to put this in a perl script and not run on the command line, then something like this will do the job:

 #! /usr/bin/perl -w use strict; # Habit of mine use 5.0100; # So we can use 'say' # Save the matching expression in a variable. # qr// tells us it a regex-like quote (http://perldoc.perl.org/functions/qr.html) my $regex = qr/__(.*?)__/; # Ordinarily, I'd write this in a way I consider to be less perl-y and more readable. # What it doing is reading from the filename supplied on STDIN and places the # contents of the file in $_. Then it runs the substitution on the string, before # printing out the result. while (<>) { $_ =~ s/$regex/{{$1}}/g; say $_; } 

The use is simple:

 ./regex myfile whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever 

This is Perl, there is a million and one way to do it!

+2
source

GNU sed

 sed ':ks/__/{{/;s/__/}}/;tk' file 

input:

 whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever blah__XXX_XX__blah_blah_blah__XX_XXX__whateverwhatever 

output:

 whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever blah{{XXX_XX}}blah_blah_blah{{XX_XXX}}whateverwhatever 
+2
source

sed does not support PCRE properties such as a non-greedy statement

I managed to get around your situation with the following change:

 echo 'whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever' | sed -e 's/__\([^_]\+_[^_]\+\)__/\{{\1}}/g' whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever 
+1
source

One way to use sed , although it’s clear that this is not the best tool for doing the job. I commented on the code to find out what happens because it seems a bit confusing:

 sed -n ' ## Insert a newline just before each "__". This is the most ## important instruction of all the script. The game is that ## newline character is the only want that sed cannot find in ## a line of data, so use it to know where there will be "__" ## to change. For each part changed the script will save it ## in hold space, but due to constraints of those (only two ## spaces) I will have to play deleting and recovering data ## several times between both. s/__/\n&/g ## Save in hold space all data until first newline. ## So it means, just before the first "__" of the line. h ; s/\n.*$// ; x ## Remove that part just saved in hold space. s/^[^\n]*\n// ## Set a label to jump it later. :a ## This is end condition. When not found any newline ## in the pattern space means that there are no more "__" to ## process, so get all data saved in hold space, print ## it and leave hold space empty ready for next line of ## the input file. /^[^\n]\+$/ { g p x s/^.*$// x b } ## This part of code will process next two input lines. ## First one has the first pair of "__" and second one has ## the end pair, so substitute to each respective curly ## braces. s/__/{{/ ## Once the substitution has been done, save it adding to ## hold space. ## I add all the line but only want to keep until first newline. ## I delete two of them because "H" command adds it one by itself. H ; x ; s/\n// ; s/\n.*$// ; x ## Delete part just processed and saved in hold space. s/^[^\n]*\n// ## Repeat same process for end pair of "__" s/__/}}/ H ; x ; s/\n// ; s/\n.*$// ; x s/^[^\n]*\n// ## Goto label "a" ba ' infile 

Paste and run it from the command line, with your two lines provided:

 whatever{{MATCH_THIS}}whateverwhatever{{AND_THIS}}whateverwhatever exten => s,n,ExecIf($[${amacode} == 1]?Set(rateparams_view={{INCOMING_RATEPARAMS_VIEW}}):Set(rateparams_view={{OUTGOING_RATEPARAMS_VIEW}})) 
+1
source

This may work for you (GNU sed):

 sed -r 's/__([^_]+(_[^_]+)*)__/{{\1}}/g' file 

or perhaps easier to understand:

 sed -r 's/__/\n/g;s/\n([^\n]*)\n/{{\1}}/g;s/\n/__/g' file 
+1
source

It works on my windows XP laptop

 input command echo whatever__MATCH_THIS__whateverwhatever__AND_THIS__whateverwhatever|sed -f a.sed output whatever{{__MATCH_THIS__}}whateverwhatever{{__AND_THIS__}}whateverwhatever where a.sed is this /__MATCH_THIS__/{ /__AND_THIS__/{ s/__MATCH_THIS__/\{\{__MATCH_THIS__\}\}/ s/__AND_THIS__/\{\{__AND_THIS__\}\}/ } } 
0
source

Source: https://habr.com/ru/post/1483953/


All Articles