AWK:从线条模式访问捕获的组

ram*_*ion 214 regex awk

如果我有一个awk命令

pattern { ... }
Run Code Online (Sandbox Code Playgroud)

和pattern使用捕获组,如何访问块中捕获的字符串?

gle*_*man 312

使用gawk,您可以使用该match函数捕获带括号的组.

gawk 'match($0, pattern, ary) {print ary[1]}' 
Run Code Online (Sandbox Code Playgroud)

例:

echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}' 
Run Code Online (Sandbox Code Playgroud)

输出cd.

请注意gawk的具体用法,它实现了相关功能.

对于便携式替代品,您可以使用match()和获得类似的结果substr.

例:

echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}'
Run Code Online (Sandbox Code Playgroud)

输出cd.

  • 是的,gxxx变体具有许多额外的GNU优点和功能. (3认同)

Pet*_*ans 160

那是一段漫步的记忆之路......

很久以前我用perl替换了awk.

显然,AWK正则表达式引擎不捕获其组.

你可能会考虑使用类似的东西:

perl -n -e'/test(\d+)/ && print $1'
Run Code Online (Sandbox Code Playgroud)

-n标志使perl像awk一样遍历每一行.

  • `gawk`!=`awk`.它们是不同的工具,大多数地方默认不提供"gawk". (14认同)
  • OP专门要求awk解决方案,所以我不认为这是一个答案. (5认同)
  • @Joppe如果没有解决方案,你不能给出awk解决方案.在第3行我解释说AWK不支持捕获组,我提供了一个替代方案,OP显然赞赏,因为这个答案被接受了.我怎么能更好地回答这个问题? (4认同)
  • 显然有人不同意.此网页来自2005年:http://www.tek-tips.com/faqs.cfm?fid = 5774它确认您无法在awk中重复使用匹配的组. (3认同)
  • 对于几乎所有的用例,我更喜欢'perl -n -p -e ...'而不是awk,因为它更灵活,功能更强大,并且在我看来语法更加灵巧. (3认同)

ops*_*psb 30

这是我一直需要的东西所以我为它创建了一个bash函数.这是基于格伦杰克曼的回答.

定义

将此添加到.bash_profile等.

function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }
Run Code Online (Sandbox Code Playgroud)

用法

捕获文件中每一行的正则表达式

$ cat filename | regex '.*'
Run Code Online (Sandbox Code Playgroud)

捕获文件中每行的第一个正则表达式捕获组

$ cat filename | regex '(.*)' 1
Run Code Online (Sandbox Code Playgroud)

  • 它与使用`grep -o`有什么不同? (2认同)
  • @OlleHärstedt 不,不能。当您没有捕获组时,它仅涵盖您的用例。在这种情况下,使用链接的“grep -o”会变得很难看。 (2认同)

Dan*_*lis 14

你可以使用GNU awk:

$ cat hta
RewriteCond %{HTTP_HOST} !^www\.mysite\.net$
RewriteRule (.*) http://www.mysite.net/$1 [R=301,L]

$ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta
http://www.mysite.net/
Run Code Online (Sandbox Code Playgroud)

  • +1.此外,任何awk:`awk'匹配($ 0,/.*(http*.*)\ $ /){print substr($ 0,RSTART,RLENGTH)}'` (11认同)
  • 那是[格伦·杰克曼的答案所说的](http://stackoverflow.com/a/4673336/9859),非常多. (5认同)
  • [类似“ RSTART”和“ RLENGTH”的引用是指与模式匹配的子字符串](http://www.grymoire.com/Unix/Awk.html#uh-47) (2认同)

小智 6

您也可以在 vanilla awk 中模拟捕获,无需扩展。虽然它不直观:

步骤 1. 使用 gensub 用一些未出现在您的字符串中的字符包围匹配项。步骤 2. 对角色使用拆分。步骤 3. 拆分数组中的每个其他元素都是您的捕获组。

$ echo 'ab cb ad' | awk '{ split(gensub(/a./,SUBSEP"&"​​SUBSEP,"g",$0),cap,SUBSEP); 打印帽[2]"|" 帽[4] ; }'
ab|ad

  • 我完全确定 gensub 是一种 gawk 主义,尽管 BusyBox awk 也有它。不过,这个答案也可以使用 gsub 来实现:`echo 'ab cb ad' | awk '{gsub(/a./,SUBSEP"&amp;"​​SUBSEP);split($0,cap,SUBSEP);print cap[2]"|"cap[4]}'` (6认同)
  • 我几乎可以肯定 `gensub` 是一个 `gawk` 特定的函数。如果你输入 `awk --version` ;-?),你会从你的 awk 中得到什么。祝你们好运。 (3认同)
  • gensub() 是一个 gawk 扩展,gawk 的手册清楚地说明了这一点。其他 awk 变体也可能实现它,但它仍然不是 POSIX。尝试 gawk --posix '{gsub(...)}' 它会抱怨 (3认同)
  • @MestreLion,你的意思是它会抱怨`gawk --posix '{gensub(...)}'`。 (2认同)
  • 尽管您对 **POSIX awk** 具有 `gensub` 函数的看法是错误的,但您的示例适用于非常有限的场景:整个模式已分组,当我只想提取“值”部分。 (2认同)
  • 已经有足够多的人评论过“gensub 是一种呆子主义”。为什么不至少编辑你的答案呢? (2认同)