Regex 带正则表达式的awk中的自定义字段分隔符:前导空格和逗号问题

Regex 带正则表达式的awk中的自定义字段分隔符:前导空格和逗号问题,regex,awk,Regex,Awk,我在stackoverflow上四处寻找解决方案,我找到了一些相关的答案,但我还没有找到一个明确的解决方案来解决我的疑问。我希望我没有问重复的问题 让我们考虑一个文件 cat > file << EOF 1 2 3 4, 5,, 6, 7 EOF 但是,如果我有前导空间,我就有一个问题。例如: 有一个前导空格 cat > file << EOF 1 2 3 4, 5,, 6, 7 EOF 两个前导空格相同 cat > file <<

我在stackoverflow上四处寻找解决方案,我找到了一些相关的答案,但我还没有找到一个明确的解决方案来解决我的疑问。我希望我没有问重复的问题

让我们考虑一个文件

cat > file << EOF
1 2  3 4, 5,, 6, 7
EOF
但是,如果我有前导空间,我就有一个问题。例如:

有一个前导空格

cat > file << EOF
 1 2  3 4, 5,, 6, 7
EOF
两个前导空格相同

cat > file << EOF
  1 2  3 4, 5,, 6, 7
EOF
$ echo " 1 2 " | awk -F' ' '{for(i=1;i<=NF;i++) print i"--> "$i}'
1--> 1
2--> 2
等等

然而,问题不仅仅在于空间。 例如

cat > file << EOF
1,2,3,
EOF
这正是我所期望的,但是

cat > file << EOF
,1,2,3
EOF
我不明白为什么

awk似乎以不同的方式对待领先的分离器。可能我误解了正则表达式的语法。事实上,我不明白为什么要将-F“”设置为前导空格 以正确的方式处理,而设置-F“[]*”则有相同的问题


最后,这是我的问题:为什么我要获得那些引导空间或引导逗号的结果,什么是正确的语法,作为字段分隔符,任何逗号和空格的数目,不管它们是否引导。

<是的,有一些不一致性,我想是为了方便。

默认分隔符忽略前导/尾随空格

$ echo " 1 2 " | awk '{for(i=1;i<=NF;i++) print i"--> "$i}'
1--> 1
2--> 2
但是,字符集

$ echo " 1 2 " | awk -F'[ ]' '{for(i=1;i<=NF;i++) print i"--> "$i}'
1-->
2--> 1
3--> 2
4-->
$echo“12”| awk-F'[]'''''{for(i=1;i 1
2--> 2
说明: 如果第一个字段为空,将所有字段左移一,将字段数减少一;同样,如果最后一个字段为空,只需减少字段数。最后一条语句用于按字段位置编号一行一行打印字段

更新
要处理空行,请在尝试修复字段之前添加一个保护
NF

好的,谢谢。因此这是awk的不一致,不是我对某件事的误解。您对如何解决我的问题有什么建议,即如何定义任意数量的逗号/空格作为字段分隔符,而不管它们的位置如何?我无法回答将逗号和空格设置为字段分隔符,并放弃前导空格的异常情况。@Gippo我误解了你的问题(因此我将删除我的答案);然而,我认为这个答案中的前两个例子是异常,或特例,第三个是正常情况。@karakfa谢谢,它起作用了。但是,我不能完全理解。请您再解释一下它是如何工作的?如果第一个字段为空$1=“”,那么它会在字段上循环以给出“名称”i-1到第i个字段,它还减少了一个字段的数量,NF-。然后它再次检查$1=“”?它应用了递归检查?我不明白为什么会发生这种情况。这就是awk的工作方式?如果我想写一个只检查一次的子句,我怎么能写它?此外,为什么需要执行第二步,如果$NF=“”然后它将NF减少1?@Enrico Maria De Angelis我不明白你为什么这么说。字段分隔符,按名称来说,就像墙一样,它的存在只是为了分隔编号的内容。一个字段分隔符,一个“墙”,不是字段,因此它没有数字。实际上,在一般情况下它没有数字。如果字符串是1,2,字段分隔符是“,”,则$1=1和$2=2,而根据您的解释,它应该是$2=“”和3美元=2,这是反对字段分隔符概念的任何有用性的。现在,我认为AWK的这种怪异行为是一个错误。“Gippo,我认为我和你之间存在一些误解。我所说的是,例如,代码>,,< /代码>(三逗号)。是一个4列CSV文件的行,4个值都是空字符串。你同意吗?如果同意,那么应该很清楚,如果一行是
1,2
FS==”,“
,那么
$1==“1”
$2==“2”
。但是,如果行是
,1
,那么
$1==”
$2==“1”
cat > file << EOF
,1,2,3
EOF
awk -F"," '{print $1}' file -->   
awk -F"," '{print $2}' file -->   1
awk -F"," '{print $3}' file -->   2
awk -F"," '{print $4}' file -->   3
$ echo " 1 2 " | awk '{for(i=1;i<=NF;i++) print i"--> "$i}'
1--> 1
2--> 2
$ echo " 1 2 " | awk -F' ' '{for(i=1;i<=NF;i++) print i"--> "$i}'
1--> 1
2--> 2
$ echo " 1 2 " | awk -F'[ ]' '{for(i=1;i<=NF;i++) print i"--> "$i}'
1-->
2--> 1
3--> 2
4-->
$ echo "   ,1 2," | 
  awk -F'[ ,]+' 'NF{if($1=="") {for(i=2;i<=NF;i++) $(i-1)=$i; NF--} 
                    if($NF=="") NF--} 
                   {for(i=1;i<=NF;i++) print i"--> "$i}'

1--> 1
2--> 2