如何替换特定数字而不是特定数字

时间:2019-02-02 04:40:25

标签: awk

我有一个像这样的文本文件

ID  
MQ2427D17-01_1_12
MQ2427D17-01_1_1
MQ2427D17-01_1_2
MQ2427D17-01_1_3
MQ2427D17-01_1_4
MQ2427D17-02_2_5
MQ2427D17-02_2_25
MQ2427D17-02_2_1
MQ2427D17-02_2_2
MQ2427D17-02_2_3
MQ2427D17-02_2_4
MQ2427D17-01_1_28
MQ3427D17-01_1_29
MQ3427D17-01_1_1
MQ3427D17-01_1_2
MQ3427D17-01_3_3
MQ3427D17-01_3_30
MQ3427D17-01_3_33

我想在结尾处更改数字,无论是1到13,还是2到14,何时是3到15,何时是4到16,何时是5到17,什么时候6到18,只要是7到19,....每当12到24。

所以输出看起来像这样

ID  
MQ2427D17-01_1_24
MQ2427D17-01_1_13
MQ2427D17-01_1_14
MQ2427D17-01_1_15
MQ2427D17-01_1_16
MQ2427D17-02_2_17
MQ2427D17-02_2_25
MQ2427D17-02_2_13
MQ2427D17-02_2_14
MQ2427D17-02_2_15
MQ2427D17-02_2_16
MQ2427D17-01_1_28
MQ3427D17-01_1_29
MQ3427D17-01_1_13
MQ3427D17-01_1_14
MQ3427D17-01_3_15
MQ3427D17-01_3_30
MQ3427D17-01_3_33

我正尝试这样做

sed 's/1/13/g' myfile.txt > modified.txt

sed = Stream EDitor
The command string:
s = the substitute command
original = a regular expression describing the number to replace
g = global (i.e. replace all and not just the first occurrence)
myfile.txt = mydata
modified.txt = the output

但这将改变他们在任何地方的数字

我不知道为什么下面的解决方案不起作用,例如在此示例数据上

ID
MQ3HHD2D17-01_1_1
MQ3HHD2D17-01_1_2
MQ3HHD2D17-01_1_3
MQ3HHD2D17-01_1_4
MQ3HHD2D17-01_1_5
MQ3HHD2D17-01_1_6
MQ3HHD2D17-01_1_7
MQ3HHD2D17-01_1_8
MQ3HHD2D17-01_1_9
MQ3HHD2D17-01_1_10
MQ3HHD2D17-01_1_11
MQ3HHD2D17-01_1_12
MQ4HHD2D17-01_2_1
MQ4HHD2D17-01_2_2
MQ4HHD2D17-01_2_3
MQ4HHD2D17-01_2_4
MQ4HHD2D17-01_2_5
MQ4HHD2D17-01_2_6
MQ4HHD2D17-01_2_7
MQ4HHD2D17-01_2_8
MQ4HHD2D17-01_2_9
MQ4HHD2D17-01_2_10
MQ4HHD2D17-01_2_11
MQ4HHD2D17-01_2_12

应该是

 ID
 MQ3HHD2D17-01_1_13
 MQ3HHD2D17-01_1_14
 MQ3HHD2D17-01_1_15
 MQ3HHD2D17-01_1_16
 MQ3HHD2D17-01_1_17
 MQ3HHD2D17-01_1_18
 MQ3HHD2D17-01_1_19
 MQ3HHD2D17-01_1_20
 MQ3HHD2D17-01_1_21
 MQ3HHD2D17-01_1_22
 MQ3HHD2D17-01_1_23
 MQ3HHD2D17-01_1_24
 MQ4HHD2D17-01_2_13
 MQ4HHD2D17-01_2_14
 MQ4HHD2D17-01_2_15
 MQ4HHD2D17-01_2_16
 MQ4HHD2D17-01_2_17
 MQ4HHD2D17-01_2_18
 MQ4HHD2D17-01_2_19
 MQ4HHD2D17-01_2_20
 MQ4HHD2D17-01_2_21
 MQ4HHD2D17-01_2_22
 MQ4HHD2D17-01_2_23
 MQ4HHD2D17-01_2_24

3 个答案:

答案 0 :(得分:4)

从您的描述中,我们可以观察到一种模式:如果结束编号低于12,则在结束编号上加上12。(此处,结束编号是指最后一个下划线之后的数字)

awk可以完成此任务。

awk -F_ -v OFS=_ '{if($NF <= 12) $NF += 12;}1' myfile.txt >modified.txt

标志:

  • -F_:输入分隔符为_
  • -v OFS=_awk的特殊变量之一,表示 O utput F ile S 引号(又称输出定界符)

其他:

  • NFawk的另一个特殊变量,表示 F ields
  • N 个数字
  • $NF:这将获取包含最后一个字段的变量。
  • {...}1:最后的1告诉awk打印所有内容。

我个人不建议使用sed,因为您需要分别将13替换为1,将14替换为14,将3替换为15,以此类推。这使它成为处理麻烦的候选人。另一方面,awk可以执行基本的数学计算(如您所见,例如+12),同时仍然能够解析输入。

输出:

ID
MQ2427D17-01_1_24
MQ2427D17-01_1_13
MQ2427D17-01_1_14
MQ2427D17-01_1_15
MQ2427D17-01_1_16
MQ2427D17-02_2_17
MQ2427D17-02_2_25
MQ2427D17-02_2_13
MQ2427D17-02_2_14
MQ2427D17-02_2_15
MQ2427D17-02_2_16
MQ2427D17-01_1_28
MQ3427D17-01_1_29
MQ3427D17-01_1_13
MQ3427D17-01_1_14
MQ3427D17-01_3_15
MQ3427D17-01_3_30
MQ3427D17-01_3_33

答案 1 :(得分:3)

请您尝试以下。

awk 'BEGIN{FS=OFS="_"} $NF>=1 && $NF<=12{$NF+=12} 1' Input_file

OR

awk 'BEGIN{FS=OFS="_"} {gsub(/\r/,"")} $NF>=1 && $NF<=12{$NF+=12} 1' Input_file

OR

tr -d '\r' < Input_file > temp && mv temp Input_file
awk 'BEGIN{FS=OFS="_"} $NF>=1 && $NF<=12{$NF+=12} 1' Input_file

在与聊天室中的用户进行故障排除之后,我们知道OP可以控制M个字符(OP不想拥有),因此建议OP通过执行tr -d '\r' < Input_file > temp && mv temp Input_file来删除它们,然后运行上面的代码。

答案 2 :(得分:0)

使用Perl单线的通用解决方案

perl -pe ' s/(\d+)$/$1<13?$1+12:$1/ge '

带有输入。

$ perl -pe ' s/(\d+)$/ $1<13 ? $1+12 : $1/ge ' learner.txt
ID
MQ2427D17-01_1_24
MQ2427D17-01_1_13
MQ2427D17-01_1_14
MQ2427D17-01_1_15
MQ2427D17-01_1_16
MQ2427D17-02_2_17
MQ2427D17-02_2_25
MQ2427D17-02_2_13
MQ2427D17-02_2_14
MQ2427D17-02_2_15
MQ2427D17-02_2_16
MQ2427D17-01_1_28
MQ3427D17-01_1_29
MQ3427D17-01_1_13
MQ3427D17-01_1_14
MQ3427D17-01_3_15
MQ3427D17-01_3_30
MQ3427D17-01_3_33

$