我有一个文件,其中包含以下格式的行:
w1#1#x w2#4#b w3#2#d ......
行中的每个单词(标记)(例如w1#1#x)由3个部分组成,第一个显示一些索引(在这种情况下为w1),第二个是整数(在这种情况下为1),第三个是一个字符(在这种情况下为x)
现在,对于每个单词(标记),我需要打印一个额外的字段,它将根据第二和第三部分的值计算(即第四部分将是第二和第三部分的函数),输出文件应该看起来像:
w1#1#x#f1 w2#4#b#f2 w3#2#d#f3 ...
哪里
f1 =函数(1,x),f2 =函数(4,b),f3 =函数(2,d)
现在,使用sed模式我可以识别每个单词(令牌)中的组件,例如,
echo $ line | sed"s /([^#] )#([^#])#([^#]*)/\1#\ 2#\ 3/g"
其中\ 2和\ 3是模式的一部分(由于此链接,我将它们称为模式的一部分)
现在,我需要使用\ 2和\ 3来计算第四部分.我已经定义了一个shell函数getInfo(),它接受2个参数并执行所需的计算并返回第4部分.问题是在sed命令中插入此函数.我试过以下:
echo $ line | sed"s /([^#] )#([^#])#([^#]*)/\1#\ 2#\ 3`getInfo\2\3`/g"
但这不起作用.Shell没有接收模式的部分作为参数.
所以问题是:
如何将模式的sed 部分传递给shell(函数)?
我可以轻松编写一个shell脚本,它会逐行拆分行并执行所需的工作,然后将文件缝合回来,但我真的很感激shell是否可以从sed命令中的sed 接收模式的一部分作为参数.
问候,
Salil Joshi
这可能对你有用:
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
Run Code Online (Sandbox Code Playgroud)
或者如果你有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
Run Code Online (Sandbox Code Playgroud)
到了一定程度,它就sed不再是完成这项工作的正确工具了。我认为这个任务已经达到了这一点(但请参阅potong的聪明答案,它表明它可以用和 来完成)。bashsed
您使用哪种替代工具?您没有显示该函数,但如果可以使用 shell 函数在 shell 中方便地计算它,那么该函数很可能awk足够强大来完成这项工作。我自己可能会求助于 Perl,但 Python(或 Ruby)也能很好地工作。所有这些都允许您编写一个函数,读取数据并将该函数应用于数据,然后再将数据写回。
尝试使用函数的问题在于sed它没有定义函数或执行 shell 函数的机制。要使用sed,您必须考虑两次遍历数据,第一次提取(唯一的)标记以进行后续处理,即将 shell 函数应用于每个标记,生成一个sed仅匹配每个标记的脚本并用其替换项替换它,然后在第二次数据传递中应用该脚本。