grep/sed/awk - 将文件中的所有“$X”替换为新的计算值“$X/10”

grep/sed/awk - Replace all "$X" in file with new computed value "$X/10"

这是我的原始文件:

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
/ Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe (  )
Seat 2: Mpeti (  )
Seat 3: Bowen (  )
Seat 4: Riccardo (  )
Seat 5: Ramman (  )
Seat 6: Reva (  )
Seat 7: Miklos (  )
Seat 9: Samlet (  )
Seat 10: Geralyn (  )
Hamlet posts small blind []
Geralyn posts big blind []
** Dealing down cards **
Monroe calls []
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls []
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [  ]

对于所有美元值“$X”,我需要将它们替换为“$X/10”(Eks。$2/10=0.2) 我可以使用以下管道命令提取美元值并将它们除以 10:

grep -o '$[[:digit:]]*' dollar.txt | sed 's/[^0-9]//g' | awk '{print /10}'

0.1
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.2
0.1
0.2
0.2
0.2

如何更改整个原始文件(或创建一个新文件)以便文件的其余部分包含所有“$X”值并替换为“$X/10”?

这个的一个实现,作为一个纯 awk 脚本(不需要 bash),可能看起来像:

#!/usr/bin/env awk -f
/[$][[:digit:]]+/ {
  while (match([=10=], /[$][[:digit:]]+/) > 0) {
    prefix = substr([=10=], 1, RSTART-1)
    suffix = substr([=10=], RSTART+RLENGTH)
    input = substr([=10=], RSTART+1, RLENGTH-1)
    output = input / 10
    [=10=] = prefix output suffix
  }
}
{ print }

如果 运行 与 ./awkscript <in.txtawk -f awkscript <in.txt,输出为:

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
0.1/0.2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( 0.2 )
Seat 2: Mpeti ( 0.2 )
Seat 3: Bowen ( 0.2 )
Seat 4: Riccardo ( 0.2 )
Seat 5: Ramman ( 0.2 )
Seat 6: Reva ( 0.2 )
Seat 7: Miklos ( 0.2 )
Seat 9: Samlet ( 0.2 )
Seat 10: Geralyn ( 0.2 )
Hamlet posts small blind [0.1]
Geralyn posts big blind [0.2]
** Dealing down cards **
Monroe calls [0.2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [0.2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ 1.7 ]

我会按照以下方式使用 GNU AWK 完成此任务,让 file.txt 内容为

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
/ Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe (  )
Seat 2: Mpeti (  )
Seat 3: Bowen (  )
Seat 4: Riccardo (  )
Seat 5: Ramman (  )
Seat 6: Reva (  )
Seat 7: Miklos (  )
Seat 9: Samlet (  )
Seat 10: Geralyn (  )
Hamlet posts small blind []
Geralyn posts big blind []
** Dealing down cards **
Monroe calls []
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls []
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [  ]

然后

awk 'BEGIN{FPAT="[^0-9]|([0-9]*)";OFS=""}{dollar=0;for(i=1;i<=NF;i+=1){if(dollar){$i*=0.1};dollar=($i=="$")};print}' file.txt

输出

#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
[=12=].1/[=12=].2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( [=12=].2 )
Seat 2: Mpeti ( [=12=].2 )
Seat 3: Bowen ( [=12=].2 )
Seat 4: Riccardo ( [=12=].2 )
Seat 5: Ramman ( [=12=].2 )
Seat 6: Reva ( [=12=].2 )
Seat 7: Miklos ( [=12=].2 )
Seat 9: Samlet ( [=12=].2 )
Seat 10: Geralyn ( [=12=].2 )
Hamlet posts small blind [[=12=].1]
Geralyn posts big blind [[=12=].2]
** Dealing down cards **
Monroe calls [[=12=].2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [[=12=].2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ .7 ]

说明:我使用 FPAT 通知 GNU AWK 该字段是(0 个或多个数字)或单个任何其他字符。然后我使用 for 循环遍历字段,首先,如果 dollar 变量成立,我将字段替换为 0.1 的值,然后如果字段等于 [=20,我将 dollar 变量设置为 true =].顺序是至关重要的,因为这意味着第一个操作是在美元字段之后立即字段。处理完 I print 行中的所有字段后。我将输出字段分隔符 (OFS) 设置为空字符串,以防止注入不需要的字符。

(在 GNU Awk 5.0.1 中测试)

如果 .2 足以满足 0.2,您可以在每个美元值的最后一位数字前加一个点:

sed -E 's/($)([0-9]*)([0-9])/./g

否则(改进,感谢potong的建议):

sed -E '
    s/$([0-9]+)([0-9])/./g
    s/$([0-9])/0./g' file
  • 对于包含两位或更多数字的美元值,删除 $ 并在最后一位数字前加一个点(有效除以 10)。
  • 任何剩余的美元价值都是一位数字。去掉$,把0.放在数字前。
  • 如果输入已经包含十进制美元值(如 .00),这将不起作用

如果你可以使用 perl 解决这个问题,解决方案将尽可能短

perl -i -pe 's{$(\d+)}{(/10)}ge' file

online demo详情:

  • -i - 内联文件更改选项
  • s{$(\d+)}{(/10)}ge - s替换命令,其中 RHS(替换部分)是一个 Perl 表达式(使用 e 标志启用),匹配所有(g) 在 $ 符号的每一行上出现,然后是一个或多个数字(捕获到第 1 组,</code>),并将每个匹配项替换为第 1 组值除以的结果10.</li> </ul> <p>如果您想明确禁止执行浮点值替换(例如 <code>.500),您可以将 $(\d+) 替换为 $(\d+)(?!\.?\d)

使用 GNU awk 进行“就地”编辑和 match() 的第三个参数:

$ awk -i inplace 'match([=10=],/(.*$)([0-9]+)(.*)/,a){ [=10=]=a[1] a[2]/10 a[3] } 1' file

$ cat file
#Game No : 1000693
***** 888poker Hand History for Game 1000693 *****
/[=11=].2 Blinds No Limit Holdem - *** 18 11 2021 10:41:44
Table DD Poker 9 Max (Real Money)
Seat 7 is the button
Total number of players : 9
Seat 1: Monroe ( [=11=].2 )
Seat 2: Mpeti ( [=11=].2 )
Seat 3: Bowen ( [=11=].2 )
Seat 4: Riccardo ( [=11=].2 )
Seat 5: Ramman ( [=11=].2 )
Seat 6: Reva ( [=11=].2 )
Seat 7: Miklos ( [=11=].2 )
Seat 9: Samlet ( [=11=].2 )
Seat 10: Geralyn ( [=11=].2 )
Hamlet posts small blind [[=11=].1]
Geralyn posts big blind [[=11=].2]
** Dealing down cards **
Monroe calls [[=11=].2]
Mpeti folds
Bowen folds
Riccardo folds
Ramman folds
Reva folds
Miklos calls [[=11=].2]
Hamlet folds
** Dealing flop ** [ As, 6s, Ah ]
** Dealing turn ** [ 8s ]
** Dealing river ** [ 4h ]
** Summary **
Monroe shows [ Jh, Td ]
Miklos shows [ Tc, Jc ]
Samlet shows [ Th, 8c ]
Geralyn shows [ Js, Ts ]
Geralyn collected [ .7 ]

如果您希望从输出中删除 $,则只需在 match().

中使用的正则表达式中将 $) 更改为 )$

以上假设每行只有 0 或 1 个 $<number>,并且所有数字都是整数。