仅当第二个图案出现时打印两个图案

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 并打印结果。