首页 > 解决方案 > 用条件交换值?

问题描述

我有一个以下文件,我想交换格式为数字(最多 3 位)@digits(最多 4 位)后跟 # 或空格/行尾的值。如果@ 后跟非数字,则不应互换它们。

样本输入

cat file1
xyz xyz xyz 123@456#1@34#123@2
xyz xyz xyz xyz xyz
test test
123@456#1@34#123@212#3@456#1@34#123@2#123@xyzxyz xyz

xyz xyz xyz

样本输出:


xyz xyz xyz 456@123#34@1#2@123
xyz xyz xyz xyz xyz
test test
456@123#34@1#212@123#456@3#34@1#2@123#123@xyzxyz xyz

xyz xyz xyz

尝试了以下逻辑,似乎需要拆分才能交换值,但无法检查条件以及如何将其保存在同一字段中

awk '{for(a=1;a<=NF;a++){if($a~/@/){split($a,b,"[@#]");val1=b[1];val2=b[2];print val1,val2}}}' file1
123 456
123 456

标签: shellawkconditional-statements

解决方案


这个简单gnu sed的应该能够完成这项工作:

sed -E 's/\<([0-9]{1,3})@([0-9]{1,4})(#|$)/\2@\1\3/g' file

xyz xyz xyz 456@123#34@1#2@123
xyz xyz xyz xyz xyz
test test
456@123#34@1#212@123#456@3#34@1#2@123#123@xyzxyz xyz

xyz xyz xyz

在这里,\<用于单词边界。

请注意,在 BSD sed 上,您必须使用[[:<:]]单词边界:

sed -E 's/[[:<:]]([0-9]{1,3})@([0-9]{1,4})(#|$)/\2@\1\3/g' file

解释:

  • \<: 字边界
  • ([0-9]{1,3}): 匹配 1 到 3 位数字
  • @: 匹配一个@
  • ([0-9]{1,4}): 匹配 1 到 4 位数字
  • (#|$): 匹配一个#或行尾

推荐阅读