如何在Bash中定义函数,用Awk提取两正则间的代码块?
解决Awk与Bash函数参数冲突的代码块提取问题
问题背景
要从文件中提取匹配**起始正则pat1到结束正则pat2**的代码块,原本直接用Awk命令可以正常工作:
$ awk '/dw_pcie_ops.*=/{inblk=1} inblk==1&&/^}/{print $0; inblk=0} inblk==1{print $0}' drivers/pci/controller/dwc/pci-meson.c static const struct dw_pcie_ops dw_pcie_ops = { .link_up = meson_pcie_link_up, .start_link = meson_pcie_start_link, };
为了复用功能,将其封装为Bash函数patinpat,但调用patinpat dw_pcie_ops.*= ^} drivers/pci/controller/dwc/pci-meson.c时,虽参数传递正常,却无法提取目标代码块。函数原定义如下:
# usage : patinpat pat1 pat2 filename function patinpat ( ) { echo 'running patinpat' echo '$1 = ' $1 echo '$2 = ' $2 echo '$3 = ' $3 awk '/"$1"/{inblk=1} inblk==1&&/"$2"/{print $0; inblk=0} inblk==1{print $0}' "$3" }
错误原因
- Awk代码被双引号包裹时,内部的
$1、$2是Awk的内置变量(代表当前行的第1、2个字段),而非Bash函数的参数 - 正则表达式被额外的双引号包裹(
/"$1"/),导致传入的正则被当作包含引号的字符串匹配,而非原始正则规则
解决方法
使用Awk的-v选项将Bash函数的参数传递给Awk变量,避免变量冲突,同时去掉正则的多余引号:
# usage : patinpat pat1 pat2 filename function patinpat() { echo 'running patinpat' echo '$1 = ' "$1" echo '$2 = ' "$2" echo '$3 = ' "$3" awk -v start="$1" -v end="$2" ' $0 ~ start { inblk = 1 } inblk == 1 { print $0 if ($0 ~ end) inblk = 0 } ' "$3" }
测试验证
调用函数:
$ patinpat dw_pcie_ops.*= ^} drivers/pci/controller/dwc/pci-meson.c
输出结果:
running patinpat $1 = dw_pcie_ops.*= $2 = ^} $3 = drivers/pci/controller/dwc/pci-meson.c static const struct dw_pcie_ops dw_pcie_ops = { .link_up = meson_pcie_link_up, .start_link = meson_pcie_start_link, };
内容的提问来源于stack exchange,提问作者Chan Kim
相关产品推荐
相关产品推荐

