【问题标题】:using sed to extract certain strings from config file使用 sed 从配置文件中提取某些字符串
【发布时间】:2020-12-11 20:28:45
【问题描述】:

我正在尝试从下面的输出中导出某些字符串,但是我没有使用 sed/awk 的经验,我需要一些建议我该如何继续。

输入:

name Cleartext-Password := "password", Service-Type := Framed-User
    Framed-IP-Address := 127.0.0.1,
    MS-Primary-DNS-Server := 8.8.8.8,
    Fall-Through = Yes,
    Mikrotik-Rate-Limit = 20M/30M

输出应该是: 名称;密码;127.0.0.1;20M;30M;

我不确定这是否是正确的方法,但我已尝试删除所需字符串之间的所有内容,例如:

sed 's/ Cleartext-Password := "/;/' 

但是我认为这是肮脏的方式而不是聪明的方式。

您能否让我知道我需要寻找什么才能为此创建有效的 sed/awk 解决方案?

【问题讨论】:

  • 只有一个样本很难说什么是足够的,但是 5-6 行的 Awk 似乎是一张票。如果令牌始终处于可预测的顺序,则可能更少。因此,不幸的是,这个问题太模糊了,在 Stack Overflow 上不是一个可以接受的问题。
  • name 是关键字还是可以包含空格的名称的占位符?您的文件总是有 5 行?
  • @cyrus "name" 始终是一个没有空格的字符串,但它可以包含点或其他特殊字符。
  • 这被标记为 [tageembedded-linux] 但你的问题没有提到任何平台。如果您在 Busybox 等严重受限的平台上需要此功能,或许可以edit 澄清您的要求。
  • 为您的问题的示例输入添加 3-4 条记录和所需的输出(无描述)。

标签: string awk sed


【解决方案1】:

您能否根据您显示的示例尝试以下操作。在现场编写和测试 https://ideone.com/eWXv3w

由于 OP 的 Input_file 具有控制 M 个字符,因此在此处的代码中添加了 gsub(/\r/,"")

awk '
BEGIN{ OFS=";" }
{ gsub(/\r/,"") }
match($0,/Cleartext-Password[^,]*/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/Cleartext-Password[^"]*|"/,"",val)
  val=$1 OFS val
  next
}
/Framed-IP-Address/{
  sub(/,$/,"")
  val=val OFS $NF
  next
}
/Mikrotik-Rate-Limit/{
  print val, $NF
  val=""
}' Input_file

解释:在程序的BEGIN 部分,根据问题将OFS 设置为分号。然后使用 awk 的 match 函数匹配来自字符串 Cleartext...Cleartext-Password[^,]* 的正则表达式,直到第一个逗号出现。如果正则表达式完美匹配,则在此处在变量 val 中捕获该子字符串。现在使用 gsub 全局替换 Cleartext-Password 中的所有内容以及根据所需输出的所有不必要的内容。

然后检查行是否包含Framed-IP-Address,如果找到,然后从行的最后一个发送替换,,并将该行的最后一个字段添加到变量val。

现在检查条件是否一行包含Mikrotik-Rate-Limit,然后在这里简单地打印 val 和最后一个字段的值,在这里也使 val 无效。

【讨论】:

  • 写在手机上会在早上添加完整的解释,因为现在是深夜:)
  • ;20M/30Msword;127.0.0.1,- 这是我在我的 debian 实验室测试的输出
  • @jakeiscool,对不起,我没听明白,如果您检查我的解决方案中提到的链接,它对我来说效果很好,如果您在这里遇到任何错误,请告诉我吗?
  • 每行末尾有^M个字符
  • 先生,现在它就像一个魅力。非常感谢你。可悲的是,我什至不知道如何开始了解您的解决方案的工作原理。对我来说,它看起来如此复杂和困难。很多东西让我学习..再次感谢您
【解决方案2】:

有很多方法可以用awk 来解决这个问题,关键是用正则表达式匹配记录的一部分,以识别您正在操作的记录,然后以所需的格式隔离所需的测试和输出.

一种方法是:

awk '
    /Cleartext-Password/ { printf "%s;%s;", $1, substr($4,2,length($4)-3) }
    /Framed-IP-Address/  { printf "%s;", substr($NF,1,length($NF)-1) }
    /Mikrotik-Rate-Limit/{ sub(/\//,";",$NF); printf "%s;\n", $NF }
' config

使用/输出示例

在名为 config 的文件中输入您的示例输入,您将收到:

name;password;127.0.0.1;20M;30M;

检查一下,如果我在哪里误解了,请告诉我。

【讨论】:

  • 谢谢您,先生,我确信我的问题将被删除,但我感谢您和其他用户为帮助我所做的一切努力。我会检查你的解决方案是如何工作的,然后尝试理解它的每一部分。
  • GNU Awk - String-Manipulation Functions 将为您提供所有使用的功能。 /match-stuff/{...} 只是确保 {...} 之间的内容仅应用于包含 "match-stuff" 的行。祝你的脚本好运。
【解决方案3】:

这可能对你有用(GNU sed):

sed -nE -e '/Cleartext-Password/{s/ .*:=\s"(.*)",.*/;\1/;h}' \
        -e '/Framed-IP-Address/{s/.*:= (.*),/\1/;H}' \
        -e '/Mikrotik-Rate-Limit/{s#.*= (.*)/(.*)#\1;\2#;H;g;y/\n/;/;p}' file

通过调用-n 选项关闭隐式打印。

通过调用-E 选项减少反斜杠。

将记录的字段存储在保持空间中,当所有字段都收集完毕后,将保持空间复制到模式空间,用字段分隔符替换换行符并打印结果。

您可能更喜欢:

sed -nE '/Cleartext-Password/{s/ .*:=\s"(.*)",.*/;\1/;h};
         /Framed-IP-Address/{s/.*:= (.*),/\1/;H};
         /Mikrotik-Rate-Limit/{s#.*= (.*)/(.*)#\1;\2#;H;g;y/\n/;/;p}' file

【讨论】:

  • 您好!我已经测试了您的解决方案,但它似乎与 RavinderSingh13 完全一样。它切断了密码和第一个字符串,可能是由于我的测试文件中存在 ^M 。请查收:pastebin.com/PbzYrCTe
  • 尝试运行 dos2unix <file 并将结果通过管道传递给 sed 命令(不带 file 参数)。
猜你喜欢
  • 2018-03-03
  • 1970-01-01
  • 2012-07-01
  • 2022-01-08
  • 2017-01-31
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多