Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing part of patterns from sed to shell

Tags:

shell

sed

I have a file which contains lines of the following format:

w1#1#x w2#4#b w3#2#d ...

Each word (token) in the line (e.g. w1#1#x) is made of 3 parts, the first showing some index (w1 in this case), the second is an integer (1 in this case) , and the third is a character (x in this case)

Now, for each word (token), I need to print an additional field which will be calculated based on value of second and third part (i.e., the 4th part will be a function of 2nd and 3rd part), and the output file should look like:

w1#1#x#f1 w2#4#b#f2 w3#2#d#f3 ...

where

f1 = function(1,x), f2 = function(4,b), f3 = function (2,d)

Now, using the sed patterns I can identify the components in every word (token), e.g.,

echo $line | sed "s/([^#])#([^#])#([^# ]*) /\1#\2#\3 /g"

where \2 and \3 are parts of the pattern (I am calling them parts of the pattern because of this link)

Now, I need to compute the 4th part using \2 and \3. I have defined a shell function getInfo() which takes 2 arguments and does the required computation and gives me back the 4th part. The problem is inserting this function in the sed command. I tried following:

echo $line | sed "s/([^#])#([^#])#([^# ]*) /\1#\2#\3`getInfo \2 \3` /g"

but this is not working. Shell is not receiving the parts of the pattern as arguments.

So the question is:

How to pass the sed parts of the pattern to a shell (function)?

I can easily write a shell script which would split the line word-by-word and do the required job and then stitch the file back, but I would really appreciate if shell can receive parts of the pattern as arguments from sed within the sed command.

Regards,

Salil Joshi

like image 906
Salil Avatar asked Jan 29 '12 13:01

Salil


People also ask

How do I print a line between two patterns in shell script?

The sed command will, by default, print the pattern space at the end of each cycle. However, in this example, we only want to ask sed to print the lines we need. Therefore, we've used the -n option to prevent the sed command from printing the pattern space. Instead, we'll control the output using the p command.

What is $P in sed?

In sed, p prints the addressed line(s), while P prints only the first part (up to a newline character \n ) of the addressed line. If you have only one line in the buffer, p and P are the same thing, but logically p should be used.

What does sed command return?

GNU 'sed' returns the following exit status error values: 0 Successful completion. 1 Invalid command, invalid syntax, invalid regular expression or a GNU 'sed' extension command used with '--posix'.

How do you use sed on a variable?

Another way to feed a literal text or a variable to stdin is by using here-string: $ sed 's/We/They/; s/Linux/Microsoft Windows/' <<< "We love Linux." They love Microsoft Windows. $ sed 's/We/They/; s/Linux/Microsoft Windows/' <<< $TEXT They love Microsoft Windows.


1 Answers

This might work for you:

func(){ echo "$1#$2#$3#$2$3"; }
export -f func
echo "w1#1#x w2#4#b w3#2#d" |
sed 's/\([^#]*\)#\([^#]*\)#\([^ ]*\) \?/echo -n "$(func \1 \2 \3) "; /g;s/$/echo ""/' |
sh
w1#1#x#1x w2#4#b#4b w3#2#d#2d 

Or if you have GNU sed:

func(){ echo "$1#$2#$3#$2$3"; }
export -f func
echo "w1#1#x w2#4#b w3#2#d" |
sed 's/\([^#]*\)#\([^#]*\)#\([^ ]*\) \?/echo -n "$(func \1 \2 \3) "; /ge;s/.$//'
w1#1#x#1x w2#4#b#4b w3#2#d#2d
like image 129
potong Avatar answered Oct 29 '22 21:10

potong