仅当第二个图案出现时打印两个图案
Print two patterns only when the second pattern occurs
只有英语科目成绩的人,如何打印名字和成绩。
换句话说,grepping for 2 pattern and print first and second pattern only when the 2nd pattern is matched.
输入:
{
"sessionId": "000001",
"name": "ABC",
"Age": "21",
"Score": {
"English": "A+",
"Mathematics": "B-",
"String Theory": "C+"
}
},
{
"sessionId": "000001",
"name": "CDE",
"Age": "21",
"Score": {
"English": "A-",
"German": "B-",
"French": "C+"
}
},
{
"sessionId": "000001",
"name": "EFG",
"Age": "21",
"Score": {
"German": "A+",
"Mathematics": "B-",
"Machine Learning": "C+"
}
},
输出
"name": "ABC",
"English": "A",
"name": "CDE",
"English": "A",
您可以使用 awk
,在第一个块中删除前导空格。在第二个块中,如果看到包含 "name" 的行,则将其存储到名为 name
的变量中,然后如果以下行之一包含 English
,则打印先前捕获的变量 name
与当前行一起。
awk -F: '{sub(/^[[:space:]]+/,"")} /name/{name=[=10=]} /English/{print name ORS [=10=]}'
"name": "ABC",
"English": "A+",
"name": "CDE",
"English": "A-",
另一个 awk
带有一点格式检查
$ awk '/"name":/ {n=[=10=]}
/"Score":/ {s=1}
s && /}/ {s=n=""}
s && /"English":/ {print n ORS [=10=]}' file | awk '='
"name": "ABC",
"English": "A+",
"name": "CDE",
"English": "A-",
检查 "English" 是否在 "Score" 元素中。
Sed 解决方案:
sed -n 's/^ *//;/name/h;/English/{H;g;p;}'
如果您的输入实际上是一个正确的 JSON 数组而不是其中的一个片段:
$ jq -r '.[] | select(.Score.English) | {name: .name, English: .Score.English} | @text' demo.json | sed 's/^{\|}$//g; s/,/\n/'
"name":"ABC"
"English":"A+"
"name":"CDE"
"English":"A-"
$ jq 'select (.Score.English) | {name, English: .Score.English}' < <(sed 's/},/}/' file) | sed -n 's/^ *//p'
"name": "ABC",
"English": "A+"
"name": "CDE",
"English": "A-"
.
$ cat tst.awk
{
gsub(/^[[:space:]]+|[[:space:]]*,?[[:space:]]*$/,"")
key =
gsub(/^"|"[^"]*$/,"",key)
f[key] = [=11=]
}
key == "English" {
print f["name"] ORS [=11=]
}
$ awk -f tst.awk file
"name": "ABC"
"English": "A+"
"name": "CDE"
"English": "A-"
如果您以后想要打印其他任何内容,则使用以上两种方法,例如Age
,您只需按照现有模式将它们添加到列表中即可。
这可能对你有用 (GNU sed):
sed -n '/name/h;/English/!b;H;g;s/^\s*//Mgp' file
使用 -n
选项打开可选打印。
复制包含 name
.
的行
丢弃不包含 English
.
的行
将包含 English
的行附加到 name
行。
用保留的内容替换当前行 space。
删除任一行开头的任何白色 space 并打印结果。
只有英语科目成绩的人,如何打印名字和成绩。
换句话说,grepping for 2 pattern and print first and second pattern only when the 2nd pattern is matched.
输入:
{
"sessionId": "000001",
"name": "ABC",
"Age": "21",
"Score": {
"English": "A+",
"Mathematics": "B-",
"String Theory": "C+"
}
},
{
"sessionId": "000001",
"name": "CDE",
"Age": "21",
"Score": {
"English": "A-",
"German": "B-",
"French": "C+"
}
},
{
"sessionId": "000001",
"name": "EFG",
"Age": "21",
"Score": {
"German": "A+",
"Mathematics": "B-",
"Machine Learning": "C+"
}
},
输出
"name": "ABC",
"English": "A",
"name": "CDE",
"English": "A",
您可以使用 awk
,在第一个块中删除前导空格。在第二个块中,如果看到包含 "name" 的行,则将其存储到名为 name
的变量中,然后如果以下行之一包含 English
,则打印先前捕获的变量 name
与当前行一起。
awk -F: '{sub(/^[[:space:]]+/,"")} /name/{name=[=10=]} /English/{print name ORS [=10=]}'
"name": "ABC",
"English": "A+",
"name": "CDE",
"English": "A-",
另一个 awk
带有一点格式检查
$ awk '/"name":/ {n=[=10=]}
/"Score":/ {s=1}
s && /}/ {s=n=""}
s && /"English":/ {print n ORS [=10=]}' file | awk '='
"name": "ABC",
"English": "A+",
"name": "CDE",
"English": "A-",
检查 "English" 是否在 "Score" 元素中。
Sed 解决方案:
sed -n 's/^ *//;/name/h;/English/{H;g;p;}'
如果您的输入实际上是一个正确的 JSON 数组而不是其中的一个片段:
$ jq -r '.[] | select(.Score.English) | {name: .name, English: .Score.English} | @text' demo.json | sed 's/^{\|}$//g; s/,/\n/'
"name":"ABC"
"English":"A+"
"name":"CDE"
"English":"A-"
$ jq 'select (.Score.English) | {name, English: .Score.English}' < <(sed 's/},/}/' file) | sed -n 's/^ *//p'
"name": "ABC",
"English": "A+"
"name": "CDE",
"English": "A-"
.
$ cat tst.awk
{
gsub(/^[[:space:]]+|[[:space:]]*,?[[:space:]]*$/,"")
key =
gsub(/^"|"[^"]*$/,"",key)
f[key] = [=11=]
}
key == "English" {
print f["name"] ORS [=11=]
}
$ awk -f tst.awk file
"name": "ABC"
"English": "A+"
"name": "CDE"
"English": "A-"
如果您以后想要打印其他任何内容,则使用以上两种方法,例如Age
,您只需按照现有模式将它们添加到列表中即可。
这可能对你有用 (GNU sed):
sed -n '/name/h;/English/!b;H;g;s/^\s*//Mgp' file
使用 -n
选项打开可选打印。
复制包含 name
.
丢弃不包含 English
.
将包含 English
的行附加到 name
行。
用保留的内容替换当前行 space。
删除任一行开头的任何白色 space 并打印结果。