Awk 在多行上设置字符串常量的格式,以提高可读性
出于学习目的,我正在为电话号码实现一个小的regexp匹配器。我的目标是可读性,而不是最短的gawk程序:Awk 在多行上设置字符串常量的格式,以提高可读性,awk,gawk,Awk,Gawk,出于学习目的,我正在为电话号码实现一个小的regexp匹配器。我的目标是可读性,而不是最短的gawk程序: # should match #1234567890 #123-456-7890 #123.456.7890 #(123)456-7890 #(123) 456-7890 BEGIN{ regexp="[0-9]{10},[0-9]{3}[-.][0-9]{3}[.-][0-9]{4},\\([0-9]{3}\\) ?[0-9]{3}-[0-9]{4}" len=spl
# should match
#1234567890
#123-456-7890
#123.456.7890
#(123)456-7890
#(123) 456-7890
BEGIN{
regexp="[0-9]{10},[0-9]{3}[-.][0-9]{3}[.-][0-9]{4},\\([0-9]{3}\\) ?[0-9]{3}-[0-9]{4}"
len=split(regexp,regs,/,/)
}
{for (i=1;i<=len;i++)
if ($0 ~ regs[i]) print $0
}
在awk中有没有一种简单的方法可以做到这一点?您可以将regexp存储在变量中,然后将它们连接起来,例如:
awk '{
COUNTRYCODE="WHATEVER_YOUR_CONTRY_CODE_REGEXP"
CITY="CITY_REGEXP"
PHONENR="PHONENR_REGEX"
THE_WHOLE_THING=COUNTRYCODE CITY PHONENR
if ($0 ~ THE_WHOLE_THING) { print "BINGO" }
}'
HTH开始{
regs[1]=“[0-9]{10}”
regs[2]=“[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}”
regs[3]=“\\([0-9]{3}\\)?[0-9]{3}-[0-9]{4}”
c=3
}
{
对于(i=1;i大家的共识似乎是,没有简单的方法可以在不干扰awk的情况下分割多行字符串?感谢其他的想法,但是让我作为程序员做我不喜欢的工作。因此我提出了这个解决方案,在我看来,它非常接近于一种可执行规范。我使用了d此处记录并处理重新更正以动态创建awk文件:
#!/bin/bash
# numbers that should be matched
read -r -d '' VALID <<'valid'
1234567890
123-456-7890
123.456.7890
(123)456-7890
(123) 456-7890
valid
# regexp patterns that should match
read -r -d '' PATTERNS <<'patterns'
[0-9]{10}
[0-9]{3}\.[0-9]{3}\.[0-9]{4}
[0-9]{3}-[0-9]{3}-[0-9]{4}
\([0-9]{3}\) ?[0-9]{3}-[0-9]{4}
patterns
gawk --re-interval 'NR==FNR{reg[FNR]=$0;next}
{for (i in reg)
if ($0 ~ reg[i]) print $0}' <(echo "$PATTERNS") <(echo "$VALID")
!/bin/bash
#应该匹配的数字
read-r-d“”有效以下链接可能包含您正在寻找的答案:
它表示,在awk脚本文件或某些Shell的命令行中,awk命令可以与makefile命令相同的方式拆分为几行。只需以反斜杠(\
)结束该行,awk将在解析时丢弃换行符。将其与字符串的隐式连接(类似于C)结合使用解决办法可能是
BEGIN {
regexp = "[0-9]{10}," \
"[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}," \
"\\([0-9]{3}\\)?[0-9]{3}-[0-9]{4}"
len = split(regexp, regs, /,/)
}
尽管如此,我还是倾向于将正则表达式直接存储在数组中的解决方案:它更好地反映了语句的意图,并且不会强迫程序员做超出要求的任何工作。此外,不需要length
函数,因为可以使用foreach语法。应该注意,awk中的数组类似于Java中的映射或Python中的字典,因为它们不将一系列整数索引与值关联。相反,它们将字符串键映射到值。即使使用整数作为键,它们也会隐式转换为字符串。因此,length
函数并不总是提供的,因为它具有误导性
BEGIN {
regs[1] = "[0-9]{10}"
regs[2] = "[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}"
regs[3] = "\\([0-9]{3}\\)?[0-9]{3}-[0-9]{4}"
}
{
for (i in regs) { # i recieves each key added to the regs array
if ($0 ~ regs[i]) {
print # by default `print' prints the whole record
break # we can stop finding a regexp
}
}
}
请注意,break
命令过早退出for
循环。如果每条记录只能打印一次,即使几个正则表达式可以匹配,这是必要的。我想介绍我最喜欢的这个问题,因为它还没有被提到。我喜欢使用awk的简单字符串附加操作at只是两个术语之间的默认运算符,如典型数学符号中的乘法:
x = x"more stuff"
将“更多内容”
附加到x
并再次将新值设置为x
。这样您就可以编写
regexp = ""
regexp = regexp"[0-9]{10}"
regexp = regexp"[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}"
regexp = regexp"\\([0-9]{3}\\) ?[0-9]{3}-[0-9]{4}"
要控制代码段之间的其他拆分字符,如我所知的大多数语言和awk之间的换行符,可以使用数组连接和拆分方法从数组生成字符串,并将字符串转换回数组,而不丢失数组的原始结构(例如换行符标记):
使用regstr=join(regexp,“,”)
添加您使用的拆分。
当然,awk中没有连接函数,但我想它非常简单
要实现,请了解上面的字符串追加操作
我的方法看起来更详细,但有一个优点,即原始数据(本部分中的regexp字符串片段)在每个片段前面都有一个字符串常量。这意味着代码可以通过一个非常简单的算法(甚至一些编辑器快捷方式)生成。我认为从regs[]数组并将每个模式放入其自己的单元格将更加自我记录,即,regs[1]=“[0-9]{10}”
…我不确定像($0~/regex/)和($0~regs[i])
这样的东西会有什么区别。另外,随着regex越来越大,您打算如何管理对它的更改,(很难看到更改的位置,可能在最右边,更重要的是,如果需要逗号字符',',则必须更改分隔符!;-)!祝您好运。您的正则表达式不正确。123.456-789或123-456.789将匹配。但它们不在您的列表中。您可能需要分组。嗨,肯特,谢谢您的关注。我可以使用带有“$0~regs[i]”表单的分组吗?还是我需要使用gensub?+1…尽管我会更改i Hi@JaypalSingh,很好!值得注意的是长度(数组)是一个扩展(即,它不是在所有现代awk实现中都可用)。
BEGIN {
regs[1] = "[0-9]{10}"
regs[2] = "[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}"
regs[3] = "\\([0-9]{3}\\)?[0-9]{3}-[0-9]{4}"
}
{
for (i in regs) { # i recieves each key added to the regs array
if ($0 ~ regs[i]) {
print # by default `print' prints the whole record
break # we can stop finding a regexp
}
}
}
x = x"more stuff"
regexp = ""
regexp = regexp"[0-9]{10}"
regexp = regexp"[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}"
regexp = regexp"\\([0-9]{3}\\) ?[0-9]{3}-[0-9]{4}"
i = 0
regexp[i++] = "[0-9]{10}"
regexp[i++] = "[0-9]{3}[-.][0-9]{3}[.-][0-9]{4}"
regexp[i++] = "\\([0-9]{3}\\) ?[0-9]{3}-[0-9]{4}"