【问题标题】:Extract two substrings from line in bash then concatenate them从 bash 中的行中提取两个子字符串,然后将它们连接起来
【发布时间】:2016-04-19 18:08:32
【问题描述】:

此解决方案将成为脚本的一部分。

给定一个错误日志,我需要提取失败状态/失败原因和用户名,然后将它们连接起来,以便可以通过电子邮件发送输出。

我的输出应该是这样的:

Operation status: failed,Job Description not updated because this is not a matching Job Description ID.,username=FOO
Operation status: failed,Job Description not updated because this is not a matching Job Description ID.,username=BAR

错误日志文件中的每一行都与此非常相似:

"{ Operation status: failed,Job Description not updated because this is not a matching Job Description ID.,Sent Data:{lastAppraisalScore=0.0, country=null, jobTitle=LABORER..., username=FOO},...sendAcctActNotif=N}}"

文件中没有省略号;每行包含的内容远远超过显示的内容,但我只显示了重要的部分。

【问题讨论】:

  • 您能分享一下您在这方面的研究成果吗?您是否尝试使用set -x 选项调试脚本?
  • 每一行都是有效的 JSON 吗?如果是这样,您可以通过将每一行传递给jq 并选择Operation statususername 键来实现此目的。
  • 我没有尝试使用set -x 选项进行调试。 egrep -o "Operation status:" input 部分返回我需要的内容,但需要提取到第一个 ., 以便我可以获取整个错误代码。
  • @TomFenech 不,这些行不是 JSON。

标签: bash shell


【解决方案1】:

简单的sed 替换似乎更合适。

sed -n '/^"{ Operation status: failed,/!b
    s///;s/,Sent.*, username=/\t/;s/}.*//p' file

这会搜索第一个表达式;如果没有找到,我们绕过这条线。否则,我们将匹配的字符串替换为空,然后继续替换掉我们不想保留的其他字符串,最后打印剩下的内容。

【讨论】:

  • 我在尝试运行代码时收到此错误:sed: can't find label for jump to `s///'
  • 尝试在b 之后添加分号。我本来希望所有sed 方言都在那里接受换行符作为语句分隔符,但显然不是。
  • 但是,我添加了一个缺失的!(不是)
【解决方案2】:

使用this answer,您可以提取部分行(如果它总是看起来相同)。然后你可以逐行处理你的文件:

while read line; do
  status=`grep -oP '(?<=Operation status:).*?(?=Sent)' <<< "$line"`
  user=`grep -oP '(?<=username=).*?(?=})' <<< "$line" | head -n 1`
  echo "Operation status:" $status "username="$user
done < file.txt

我的示例文件.txt:

{ Operation status: failed1,Job Description not updated because this is not a matching Job Description ID.,Sent Data:{lastAppraisalScore=0.0, country=null, jobTitle=LABORER..., username=FOO1}, {username=BAR1}...sendAcctActNotif=N}}
{ Operation status: failed2,Job Description not updated because this is not a matching Job Description ID.,Sent Data:{lastAppraisalScore=0.0, country=null, jobTitle=LABORER..., username=FOO2}, {username=BAR2}...sendAcctActNotif=N}}
{ Operation status: failed3,Job Description not updated because this is not a matching Job Description ID.,Sent Data:{lastAppraisalScore=0.0, country=null, jobTitle=LABORER..., username=FOO3}, {username=BAR3}...sendAcctActNotif=N}}

我的输出:

Operation status: failed1,Job Description not updated because this is not a matching Job Description ID., username=FOO1
Operation status: failed2,Job Description not updated because this is not a matching Job Description ID., username=FOO2
Operation status: failed3,Job Description not updated because this is not a matching Job Description ID., username=FOO3

【讨论】:

  • 这行得通,非常感谢。但是,我刚刚意识到错误日志的每一行都有两个username= 实例,所以都被返回了!如何只返回每行中用户名的第一个实例?
  • @sharpmartin6 你可以使用 | head -n 1 保留第一个元素(第一行)。看看我的编辑
  • 感谢您的快速回复。 | head -n 1 仅返回文件中的第一个元素。是否可以使用grep 仅返回每行中用户名的第一个实例?
猜你喜欢
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 2016-09-24
  • 2021-10-04
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
相关资源
最近更新 更多