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
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.
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.
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'.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With