Regex 正则表达式:使用AWK gsub的异常模式

Regex 正则表达式:使用AWK gsub的异常模式,regex,awk,gsub,string-substitution,Regex,Awk,Gsub,String Substitution,我有一个数据文件(cou.data) 此数据中只有空格,但没有选项卡 我想用“:”替换所有空格,但保留保留空格的国家名称不变 也就是说,我想要的输出应该如下所示: USSR:8649:275:Asia Cananda:3852:25:North America China:3705:1032:Asia USA:3615:237:North America Brazil:3286:134:South America India:1267:746:Asia Mexico:762:78:North A

我有一个数据文件(cou.data)

此数据中只有空格,但没有选项卡

我想用“:”替换所有空格,但保留保留空格的国家名称不变

也就是说,我想要的输出应该如下所示:

USSR:8649:275:Asia
Cananda:3852:25:North America
China:3705:1032:Asia
USA:3615:237:North America
Brazil:3286:134:South America
India:1267:746:Asia
Mexico:762:78:North America
France:211:55:Europe
Japan:144:120:Asia
Germany:96:61:Europe
England:94:56:Europe
Taiwan:55:144:Asia
North Korea:44:2134:Asia
我绞尽脑汁,只能写这个

awk '{ gsub(/([a-zA-Z] +[0-9]|[0-9] +[a-zA-Z]|[0-9] +[0-9])/, ":"); print }' cou.data
但结果并不正确

USS:64:7:sia
Canand:85::orth America
Chin:70:03:sia
US:61:3:orth America
Brazi:28:3:outh America
Indi:26:4:sia
Mexic:6::orth America
Franc:1::urope
Japa:4:2:sia
German:::urope
Englan:::urope
Taiwa::4:sia
North Kore::13:sia
有些本不该拆下的零件不见了

如何修改我的AWK代码,或者是否有一个简单的解决方案来获得我想要的

ps


awk'{print gensub(/([a-zA-Z])([a-zA-Z])/,“\\1~\\3”,“g”,“$0”)cou.data | sed-r的/+/:/g;s/~//g'

您需要捕获组和反向引用,这不是所有的
awk
实现都支持的
GNU awk
支持使用
gensub
。。我建议改用
sed

$ sed -E 's/ +([0-9])/:\1/g; s/([0-9]) +/\1:/g' ip.txt
USSR:8649:275:Asia
Cananda:3852:25:North America
China:3705:1032:Asia
USA:3615:237:North America
Brazil:3286:134:South America
India:1267:746:Asia
Mexico:762:78:North America
France:211:55:Europe
Japan:144:120:Asia
Germany:96:61:Europe
England:94:56:Europe
Taiwan:55:144:Asia
North Korea:44:2134:Asia
  • -E
    要启用ERE,某些sed版本需要
    -r
    而不是
    -E
  • s/+([0-9])/:\1/g
    匹配一个或多个空格,后跟一个数字。我们只需要替换空格,但保留数字不变。因此,捕获数字并使用反向参考在替换部分中参考它
  • s/([0-9])+/\1:/g
    这将涵盖数字后跟空格的情况
  • 捕获组的定义是将正则表达式放在
    ()
    -从左到右,
    \1
    指第一个这样的组,
    \2
    指第二个这样的组,依此类推

使用
perl
,您可以避免使用捕获组

perl -pe 's/ +(?=\d)|\d\K +/:/g' ip.txt
+(?=\d)|\d\K+
仅当后跟数字或后跟数字时才匹配空格


对于
GNU awk
,有关语法和详细信息,请参阅

awk '{$0=gensub(/ +([0-9])/, ":\\1", "g", $0);
      print gensub(/([0-9]) +/, "\\1:", "g", $0)}' ip.txt 

您需要捕获组和反向引用,这不是所有
awk
实现都支持的
GNU awk
支持使用
gensub
。。我建议改用
sed

$ sed -E 's/ +([0-9])/:\1/g; s/([0-9]) +/\1:/g' ip.txt
USSR:8649:275:Asia
Cananda:3852:25:North America
China:3705:1032:Asia
USA:3615:237:North America
Brazil:3286:134:South America
India:1267:746:Asia
Mexico:762:78:North America
France:211:55:Europe
Japan:144:120:Asia
Germany:96:61:Europe
England:94:56:Europe
Taiwan:55:144:Asia
North Korea:44:2134:Asia
  • -E
    要启用ERE,某些sed版本需要
    -r
    而不是
    -E
  • s/+([0-9])/:\1/g
    匹配一个或多个空格,后跟一个数字。我们只需要替换空格,但保留数字不变。因此,捕获数字并使用反向参考在替换部分中参考它
  • s/([0-9])+/\1:/g
    这将涵盖数字后跟空格的情况
  • 捕获组的定义是将正则表达式放在
    ()
    -从左到右,
    \1
    指第一个这样的组,
    \2
    指第二个这样的组,依此类推

使用
perl
,您可以避免使用捕获组

perl -pe 's/ +(?=\d)|\d\K +/:/g' ip.txt
+(?=\d)|\d\K+
仅当后跟数字或后跟数字时才匹配空格


对于
GNU awk
,有关语法和详细信息,请参阅

awk '{$0=gensub(/ +([0-9])/, ":\\1", "g", $0);
      print gensub(/([0-9]) +/, "\\1:", "g", $0)}' ip.txt 

您可以使用反向引用来包含您希望保留在gnu awk中的原始部分。使用gensub并向正则表达式添加反向引用,可以得到以下结果

gawk '{ print gensub(/(([a-zA-Z]) +([0-9]))|(([0-9]) +([a-zA-Z]))|(([0-9]) +([0-9]))/, "\\2\\5\\8:\\3\\6\\9", "g"); }' file

请参见

您可以使用反向引用来包括您希望保留在gnu awk中的原始部分。使用gensub并向正则表达式添加反向引用,可以得到以下结果

gawk '{ print gensub(/(([a-zA-Z]) +([0-9]))|(([0-9]) +([a-zA-Z]))|(([0-9]) +([0-9]))/, "\\2\\5\\8:\\3\\6\\9", "g"); }' file

请参见

谢谢Inian,忘了提及使用gensub需要gnu awk,wil modifytriple-back-slash是一个打字错误或您系统上的一些奇怪要求?我的错误。在没有
标记的情况下键入,第一个双反斜杠显示为一个。谢谢顺便说一句,我很喜欢你的解决方案。谢谢伊尼安,忘了提到使用gensub需要gnu awk,wil modifytriple back slash是一个打字错误,或者你的系统上有一些奇怪的要求?我错了。在没有
标记的情况下键入,第一个双反斜杠显示为一个。谢谢顺便说一下,我很喜欢你的解决方案。awk'{print gensub(/([a-zA-Z])([a-zA-Z])/,“\\1~\\3”,“g”,“$0”)cou.data | sed-r's/+/:/g;s/~//g'你觉得这个方法怎么样?我认为除了作为学习尝试之外,这个方法没有任何好处。。。你能解释一下你为什么要那样做吗?如果输入包含
~
,并且awk代码可以用sed完成,那么为什么要用awk+sed呢?是的,你是对的。只是练习使用gensub。sed可以做得很好。Thanksawk'{print gensub(/([a-zA-Z])([a-zA-Z])/,“\\1~\\3”,“g”,“$0”)cou.data | sed-r's/+/:/g;s/~//g'你觉得这个方法怎么样?我认为除了作为学习尝试之外,这个方法没有任何好处。。。你能解释一下你为什么要那样做吗?如果输入包含
~
,并且awk代码可以用sed完成,那么为什么要用awk+sed呢?是的,你是对的。只是练习使用gensub。sed可以做得很好。谢谢你的感谢谢谢你的感谢