【问题标题】:grep a specific string and replace the file with sedgrep 特定字符串并用 sed 替换文件
【发布时间】:2017-09-25 04:11:29
【问题描述】:

我需要一些解决方案来替换一些字符串。 我在内容上有一个“文件”:

23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, 平, OK, 1, 2016-08-25 16:05:04
23689, SSH 服务, OK, 1, 2016-08-25 16:05:49
23693, 系统可用空间, OK, 97.9560, 2016-08-25 16:06:49
23713, 系统可用空间, OK, 88.0078, 2016-09-20 18:02:22
23745, C:\免费, OK, 63.2227, 2016-09-21 10:57:03

我使用这段代码来获取“免费”值,如下所示:

 grep Free file.txt |grep OK | cut -d K -f 2 |cut -d , -f 2 |cut -d . -f 1

然后我得到了这个结果:

97
88
63

我需要使用以下代码在结果中插入“%”:

 grep Free rs.txt |grep OK | cut -d K -f 2 |cut -d , -f 2 |cut -d . -f 1 |sed 's/$/%/g'

结果如下:

97%
88%
63%

我的问题是,如何用新结果“97%”等替换文件上的值,例如“97.9560”等。
请给我一个建议。 谢谢

【问题讨论】:

  • 我认为将浮点值向上或向下舍入并不重要?
  • @l'L'l 是的,我将浮点数舍入对我来说并不重要。

标签: bash sed grep


【解决方案1】:

要替换文件中的值:

sed -E -i.bak 's/(Free.*OK,[^.]*)[.][^,]*/\1%/' file.txt

例子:

$ sed -E -i.bak 's/(Free.*OK,[^.]*)[.][^,]*/\1%/' file.txt
$ cat file.txt
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03

工作原理

  • -E

    这告诉 sed 使用扩展的正则表达式。这减少了我们需要的反斜杠的数量。

  • -i.bak

    这告诉就地更改文件,留下一个备份文件。

  • s/(Free.*OK,[^.]*)[.][^,]*/\1%/

    这告诉 sed 进行您需要的替换。在这种情况下,sed 会查找与正则表达式 (Free.*OK,[^.]*)[.][^,]* 匹配的文本。这匹配 Free 后跟 OK, 后跟除句点之外的任何内容,然后是句点,然后是除逗号之外的任何内容。括号导致从 Free 到句点之前的最后一个字符的所有内容都保存在第 1 组中。

    匹配的文本被替换为\1%,这意味着属于第1组的文本\1,后跟一个百分号%

【讨论】:

  • "这减少了我们需要的反斜杠的数量。" -- 我在你的 RE 中没有看到任何需要扩展 RE 的东西;如果省略,我也看不到任何需要额外的反斜杠的东西。另外,我会将[.] 替换为\.
  • @Sundeep -- 感谢您澄清这一点。 John1024 -- 很好的答案。
  • 感谢@John1024 的帮助和解释
【解决方案2】:

这里是awk版本解决方案:

awk -v OFS=, -F, '/Free.*OK/ {split($4,a,"."); $4=a[1]"%"}1' infile
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03

解释:

awk 命令将仅对包含Free 后跟OK 的行执行操作。由于此文件是 csv 文件,因此获取第 4 个字段并拆分为由 . 分隔的两部分。在附加% 符号后打印感兴趣的部分。

sed 最适合查找和替换任务,因为它支持就地替换。但是可以通过awk 使用以下方式实现:

awk -v OFS=, -F, '/Free.*OK/ {split($4,a,"."); $4=a[1]"%"}1' infile > infile.tmp && mv infile.tmp infile

【讨论】:

  • 干得好;我们同时编写了相同的脚本。我更喜欢awk -F, '/System Free Space/ {split($4, a, /[.]/); $4 = a[1] "%"} {print}',因为不需要OFS,而且IMO 以1 结尾表示打印不明确。 @dongk:awk 是你的朋友。每当您发现自己使用 cut & sed 管道时,可以肯定的是,awk 会更简洁明了。
【解决方案3】:

一对perl解决方案

$ perl -pe 's/OK,\s*\d+\K\.\d+/%/ if /Free/' ip.txt
23674, ICMP ping, OK, 1, 2016-08-25 17:11:02
23686, Ping, OK, 1, 2016-08-25 16:05:04
23689, SSH Service, OK, 1, 2016-08-25 16:05:49
23693, System Free Space, OK, 97%, 2016-08-25 16:06:49
23713, System Free Space, OK, 88%, 2016-09-20 18:02:22
23745, C:\ Free, OK, 63%, 2016-09-21 10:57:03
  • OK,\s*\d+\K 正向后视,OK, 后跟零个或多个空格和一个或多个数字
  • \.\d+ 点后跟一位或多位数字
  • 替换文本为%,仅在输入行包含Free时应用

另一种方法是在, 上拆分输入行并更改第4 个字段

perl -F, -le '$F[3] =~ s/\.\d+/%/ if /Free/; print join",", @F' ip.txt 

如果结果符合预期,可以使用

perl -i没有备份

perl -i.bkp 带备份

【讨论】:

    猜你喜欢
    • 2014-01-13
    • 2018-02-24
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 2021-11-17
    相关资源
    最近更新 更多