首页 > 解决方案 > bash、awk 和/或 sed 清理具有特殊格式的字符串

问题描述

在我正在处理的脚本中,我必须将字符串清理为我需要的格式。

每个字符串的结构:(邮政编码、街道名称、号码、扩展名):

最终紧随其后

结果字符串应为 4 位数字、2 个字母、数字,如果是扩展名,则后跟 x 和扩展名的字母或数字

下面是一些例子:

我从

echo "1019RXJavakade254" | awk '{print substr($0,0,6)}'

获取邮政编码,然后我认为我应该使用“打印匹配”,但我无法从那里得到它。

字符串单独传递并在脚本的下一步中使用。最初它们来自 csv 文件,但字符串来自的列(组合)总是不同的。脚本的第一部分正在处理它并创建这个源字符串。生成的字符串将放回一列中,我可以将其作为最后一列添加到原始 csv 文件中

我知道关于前 6 个字符之后的数字以及是否存在扩展名的问题。所以在我看来,工作流程应该是这样的:前 6 个字符应该是 4 个数字,2 个字母,如果不是总结果是空的。跳过字符 7 和 8 并抓住字符 8 之后遇到的第一组数字,即数字,之后的所有其他数字都是扩展名。扩展永远不会直接以数字开头。只有在扩展的情况下,两者之间才有一个 x。扩展名应去除其他字母数字字符。

这应该涵盖最多,其余的将有延迟交付:)


解决了

@kvantour感谢您的回答。我也稍微更改了代码以获取非大写字母。结果是一个更大的 applescript 的一部分,它在公司的 Xserve 上无人看管地运行。所以我现在使用的代码是

set KixCodeSourceClean to do shell script "echo " & KixCodeSource & " | awk '/^[0-9]{4}[a-zA-Z]{2}.+[0-9]+[- ].+$/{match(substr($0,8),/[0-9]+[- ].+$/);s=substr($0,7+RSTART,RLENGTH); sub(/[- ]/,\"x\",s);print substr($0,1,6)s;next} /^[0-9]{4}[a-zA-Z]{2}.+[0-9]+[a-zA-Z].*$/{match(substr($0,8),/[0-9]+[a-zA-Z].*$/);s=substr($0,7+RSTART,RLENGTH);match(s,/[0-9]+/);print substr($0,1,6)substr(s,1,RLENGTH)\"x\"substr(s,RLENGTH+1);next} /^[0-9]{4}[a-zA-Z]{2}.+[0-9]+$/{ match(substr($0,8),/[0-9]+$/);s=substr($0,7+RSTART);print substr($0,1,6)s;next}'"

它完美地工作并且是一个单线器,在这种情况下我更喜欢它。我经常使用这种方法。跳进跳出 Applescript 并使用 unix shell 更快地解决问题。

标签: bashshellawksed

解决方案


提取邮政编码和扩展名的几个要求,因此将结果流水线以额外sed部署在这里。

$ str="1066EC1eLouwesweg6"
$ sed -r 's/(^[0-9]{4}[A-Z]{2})..[^0-9]*(.*)/\1\2/' <<< "$str" | sed 's/-/x/' | sed -r '/[^x]/ s/(.*[0-9]+)([A-Z]+$)/\1x\2/'
1066EC6

简要说明,

  1. sed -r 's/(^[0-9]{4}[A-Z]{2})..[^0-9]*(.*)/\1\2/' <<< "$str": 先过滤掉街道名称。
  2. sed 's/-/x/': 如果存在,将 '-' 替换为 'x'
  3. sed -r '/[^x]/ s/(.*[0-9]+)([A-Z]+$)/\1x\2/':如果到现在为止的结果不存在'x',则在数字和字母之间添加'x'。

推荐阅读