英文:
How to parse an input in Bash
问题
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
英文:
I am new to Bash and have an input file.log with the following contents:
ok: [test_performance=10.50.100.82] => {
"msg": [
[
"DeviceName:78BAY08V2A/10",
"DeviceName:GH7AK1A02097/10"
]]}
ok: [test_1=10.50.101.84] => {
"msg": [
[
"DeviceName:8K251FDD4000D1/13",
"DeviceName:99071JEGR10369/12"
]]}
I want to get output as below:
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
I tried below command but it is not working. What can I try next?
grep -C 3 "DeviceName:" file.log | xargs | sed 's/ok/\n/g' | sed 's|[]{}[]||g' | sed 's/msg//g' | sed 's/ =>/,/g' | awk -F ":" '{print $4,$5}' | awk -F "--" '{print $1}' | sed 's/, /,/g' | sed 's/, /-/g' | sed 's/ //g' | grep -E 'arda|kobra|pipeline|performance|integration|feature|kare|yjr' | sed 's/=/,/g' | sed 's/\(.*\)-/,/' | sed 's/-/,/g' | tee -a file2.csv
答案1
得分: 2
使用GNU awk,使用"
、:
、=
、]
和[
作为字段分隔符:
awk -F '[":=\\]\\[]' '/^ok/{ok=$3 "," $4} /DeviceName/{print ok "," $3}' file.log
输出:
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
英文:
With GNU awk use "
, :
, =
, ]
and [
as field separators:
awk -F '[":=\\]\\[]' '/^ok/{ok=$3 "," $4} /DeviceName/{print ok "," $3}' file.log
Output:
<pre>
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
</pre>
答案2
得分: 1
使用您提供的示例,请尝试以下GNU awk
代码。它将选择从ok:
到}
的行,并根据要求处理它们。
awk -v RS='(^|\n)ok: \\[[^}]*' '
RT{
match(RT,/ok: \[([^=]*)=([^]]*)\]/,arr)
val=arr[1]","arr[2]
while(match(RT,"DeviceName:([^\"]*)",arr)){
print val","arr[1]
RT=substr(RT,RSTART+RLENGTH)
}
}
' Input_file
请注意,这只是翻译的代码部分。如果您需要进一步的解释或帮助,请提出具体问题。
英文:
With your shown samples please try following awk
code, written and tested in GNU awk
. This will pick up lines from ok:
to till }
and process them as per requirement.
awk -v RS='(^|\n)ok: \\[[^}]*' '
RT{
match(RT,/ok: \[([^=]*)=([^]]*)\]/,arr)
val=arr[1]","arr[2]
while(match(RT,/"DeviceName:([^"]*)"/,arr)){
print val","arr[1]
RT=substr(RT,RSTART+RLENGTH)
}
}
' Input_file
答案3
得分: 1
以下是已翻译的部分:
输入看起来像是以ok: [test_performance=10.50.100.82] =>
这样的标签为前缀的JSON对象列表。因此,解析的任务可以分为两个部分:
- 解析前缀。
- 解析JSON对象。
第一部分看起来不像是一个众所周知的格式,所以我会使用awk、perl或sed来解析它。对于JSON部分,有一个流行的工具叫做jq
。
以下是使用sed
和jq
的可能解决方案之一:
sed -e 's/\(^ok: .* => \){/"":{/;
1{s/^/{/};
${s/$/}/};
2~1{s/"ok:/,"ok:/}
' file.log | jq --raw-output -e '.|to_entries|.[]|. as $p|.[]
|$p.value.msg|.[]|.[]
|sub("^DeviceName:";"") as $d
|$p.key|capture("ok: \\[(?<test>.*)=(?<ip>.*)\\]")
|.test+","+.ip+","+$d'
其中,sed
命令将整个输入转化为一个JSON对象。它会:
- 在第一行之前添加大括号(
1{s/^/{/}
) - 在最后一行之后添加大括号(
${s/$/}/}
) - 用双引号包围“ok:...”前缀。
然后,结果的JSON对象被传递给jq
命令。关于其余部分,我建议读者查阅文档:
man sed
man jq
选择合适的工具
虽然从技术上讲,可以使用awk、sed甚至bash来解析JSON,但我们应该避免这样做,因为这些是通用工具。实现正确的解析器需要一个遵循整个JSON规范的程序。
类似地,生成CSV数据实际上需要专门编写用于此目的的软件。因此,个人而言,我不会在生产环境中使用上述命令。一个正确的解决方案涉及使用比bash、awk或sed更强大的编程语言。只要使用适当的库,Perl、PHP或Node.js脚本都是合适的选择。
英文:
The input looks like a list of JSON objects prefixed with labels like ok: [test_performance=10.50.100.82] =>
. So the task of parsing can be divided into two parts:
- Parsing the prefixes.
- Parsing the JSON objects.
The first part doesn't look like a well-known format, so I'd parse it using awk, perl, or sed. For the JSON part, there is a popular jq
tool.
Here is one of the possible solutions using sed
and jq
:
sed -e 's/\(^ok: .* => \){/"":{/;
1{s/^/{/};
${s/$/}/};
2~1{s/"ok:/,"ok:/}
' file.log | jq --raw-output -e '.|to_entries|.[]|. as $p|.[]
|$p.value.msg|.[]|.[]
|sub("^DeviceName:";"") as $d
|$p.key|capture("ok: \\[(?<test>.*)=(?<ip>.*)\\]")
|.test+","+.ip+","+$d'
Where the sed
command makes a JSON object out of the whole input. It
- Adds curly braces before the first line(
1{s/^/{/}
) and after the last line(${s/$/}/}
). - Surrounds the "ok:..." prefixes with double quotes.
Then the resulting JSON object is piped to the jq
command. For the rest, I suggest the reader refer to the documentation:
man sed
man jq
.
Choosing the right tool
While it is technically possible to parse JSON with awk, sed, or even bash, we should avoid doing so because these are general-purpose tools. Implementing a correct parser requires a program that adheres to the entire JSON specification.
Similarly, generating CSV data actually requires software specifically written for this purpose. Therefore, personally, I wouldn't use the command above in a production environment. A proper solution involves using a programming language that is more powerful than bash, awk, or sed. Using a Perl, PHP, or Node.js script would be suitable as long as the appropriate libraries are utilized.
答案4
得分: 1
这是一个与被接受的awk答案有些相似的sed脚本处理过程脚本。请注意,env -S
是GNU coreutils对env
的扩展。
如果一行以ok:
开头,则将该行复制到保持缓冲区(h
)。
如果一行包含DeviceName:
,则将保持缓冲区附加到模式缓冲区(G
)。提取、格式化和排序模式缓冲区中现在有两行的三个字段,并打印(s/.../p
)结果。
并像这样运行它:
$ ./process file.log
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
英文:
Here is a sed script process script somewhat similar to the accepted awk answer. Note env -S
is a GNU coreutils extension of env
.
If the line starts with ok:
copy the line to the hold buffer (h
).
If the line contains DeviceName:
append the hold buffer to the pattern buffer (G
). Extract and format and order the 3 fields of the now two lines in the pattern buffer and print (s/.../p
) the result.
#!/usr/bin/env -S sed -E -n -f
/^ok:/ h
/DeviceName:/ {
G
s/.*:([^"]*).*\n.*\[([^=]*)=([^]]*).*/,,/p
}
and run it like this:
$ ./process file.log
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
答案5
得分: 0
这是一个使用case
模式匹配的Bash脚本process
:
#!/bin/bash
while read -r line
do
case "$line" in
ok:*)
line=${line#*[}
line=${line%]*}
field12=${line/=/,}
;;
*DeviceName:*)
line=${line#*:}
field3=${line%\"*}
echo "$field12,$field3"
;;
esac
done
你可以像这样运行它:
$ ./process < file.log
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
英文:
Here is a bash script process
that uses the magic of case
pattern matching:
#!/bin/bash
while read -r line
do
case "$line" in
ok:*)
line=${line#*[}
line=${line%]*}
field12=${line/=/,}
;;
*DeviceName:*)
line=${line#*:}
field3=${line%\"*}
echo "$field12,$field3"
;;
esac
done
and you would run it like this:
$ ./process < file.log
test_performance,10.50.100.82,78BAY08V2A/10
test_performance,10.50.100.82,GH7AK1A02097/10
test_1,10.50.101.84,8K251FDD4000D1/13
test_1,10.50.101.84,99071JEGR10369/12
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论