Awk 是否有一个字段存储正则表达式中使用的确切字段分隔符FS,相当于RS的RT?
在这方面,我们可以阅读: 当Awk 是否有一个字段存储正则表达式中使用的确切字段分隔符FS,相当于RS的RT?,awk,gnu,Awk,Gnu,在这方面,我们可以阅读: 当RS是单个字符时,RT包含相同的单个字符。但是,当RS是正则表达式时,RT包含与正则表达式匹配的实际输入文本 此变量RT在中非常有用 类似地,我们可以将正则表达式设置为字段分隔符。例如,在这里我们允许它是“;”或“|”: $gawk-F';“”{print NF}' 是否有办法使用用于拆分每个字段的特定字段分隔符“重新打包”字段 使用gnu awk,使用提供的正则表达式为匹配的分隔符提供额外的第四个参数: s=“你好;你好吗” awk'split($0,flds,/[
RS
是单个字符时,RT
包含相同的单个字符。但是,当RS
是正则表达式时,RT
包含与正则表达式匹配的实际输入文本
此变量RT
在中非常有用
类似地,我们可以将正则表达式设置为字段分隔符。例如,在这里我们允许它是“;”或“|”:
$gawk-F';“”{print NF}'
是否有办法使用用于拆分每个字段的特定字段分隔符“重新打包”字段
使用gnu awk
,使用提供的正则表达式为匹配的分隔符提供额外的第四个参数:
s=“你好;你好吗”
awk'split($0,flds,/[| |]/,seps){for(i=1;seps中的i;i++)printf“%s%s”,flds[i],seps[i];print flds[i]}'split的另一种选择是使用match查找字段分隔符并将其读入数组:
awk-F'[|]'{
str=$0;#将str设置为行
while(match(str,FS)){#通过字段分隔符的rach匹配进行循环
map[cnt+=1]=substr(str,RSTART,RLENGTH);#创建一个字段分隔符数组
str=substr(str,RSTART+RLENGTH)#将str设置为匹配字符串后的字符串其余部分
}
对于(i=1;iAs,gawk有split()
(和patsplit()
,即FPAT
,正如split()
是FS
-参见)来做你想做的事情。如果你想用POSIX awk实现同样的功能,那么:
$ cat tst.awk
function getFldsSeps(str,flds,fs,seps, nf) {
delete flds
delete seps
str = $0
if ( fs == " " ) {
fs = "[[:space:]]+"
if ( match(str,"^"fs) ) {
seps[0] = substr(str,RSTART,RLENGTH)
str = substr(str,RSTART+RLENGTH)
}
}
while ( match(str,fs) ) {
flds[++nf] = substr(str,1,RSTART-1)
seps[nf] = substr(str,RSTART,RLENGTH)
str = substr(str,RSTART+RLENGTH)
}
if ( str != "" ) {
flds[++nf] = str
}
return nf
}
{
print
nf = getFldsSeps($0,flds,FS,seps)
for (i=0; i<=nf; i++) {
printf "{%d:[%s]<%s>}%s", i, flds[i], seps[i], (i<nf ? "" : ORS)
}
}
我们将得到以下输出,其中每个字段显示为字段编号,然后是[…]
中的字段值,然后是
中的分隔符,所有这些都在{…}
中(请注意,如果FS是”
且记录以空格开头,则填充seps[0]
):
$awk-F'[,|]'-F tst.awk文件1
你好,你好吗
{0:[]}{1:[你好;你好]}{2:[你好]}
$awk-f tst.awk文件2
你好,你好吗
{0:[]}{1:[你好]<>}{2:[你好]<>}{3:[你是吗]}
$awk-f tst.awk文件3
你好,你好吗
{0:[]<>}{1:[你好]<>}{2:[你好]<>}{3:[你是吗]}
jfyi这是应用同一个正则表达式两次。一次用于字段拆分,第二次用于捕获分隔符。如果拆分正则表达式很复杂,那么它会减慢速度。您可能需要更改(或讨论)的另一件事是循环范围-使用defaullt FS时,seps
数组可以从0开始,因为seps[0]然后保存flds[1]之前出现的空白,通常在字段拆分过程中会被丢弃。这里可能值得一提的是,您不能将常量regexp传递给用户定义的函数,因此,当您可以执行split($0,arr,/re/)
时,您不能编写自己的函数foo()
和dofoo($0,arr,/re/)
,您必须将其称为foo($0,arr,“re”)
而不是使用动态regexp,因为/re/
在该上下文中意味着($0~/re/?1:0)
。GNU awk有一个称为强类型regexp的增强功能,它通过在常量regexp前面加上@
前缀来解决该问题,例如foo($0,arr,@/re/)
-看到了,很高兴知道。我从来都不知道@/re/
@fedorqui'sostoppharming',它们被允许作为split()
的参数,你只是忘了引用你用来初始化awk变量的字符串,试试gawk-v patt='@/“{print split($0,a,patt)}“哦,你说得对,@EdMorton!事实上,现在我注意到我对文档的理解是另一种方式:它在split和others中可以使用(强类型regexp常量不能像常规regexp常量那样在任何地方都使用,因为这会使语言更加混乱。相反,你只能在某些上下文中使用它们)
$ head file{1..3}
==> file1 <==
hello;how|are you
==> file2 <==
hello how are_you
==> file3 <==
hello how are_you
$ awk -F'[,|]' -f tst.awk file1
hello;how|are you
{0:[]<>}{1:[hello;how]<|>}{2:[are you]<>}
$ awk -f tst.awk file2
hello how are_you
{0:[]<>}{1:[hello]< >}{2:[how]< >}{3:[are_you]<>}
$ awk -f tst.awk file3
hello how are_you
{0:[]< >}{1:[hello]< >}{2:[how]< >}{3:[are_you]<>}