仅在出现第二种图案时才打印两种图案

时间:2019-04-29 18:09:43

标签: awk sed text-processing

仅当某人具有英语主题分数时,如何才能使用“分数”打印名称。

换句话说,grepping 2个图案并仅在第2个图案匹配时才打印第一个和第二个图案。

输入:

            {
                "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",

6 个答案:

答案 0 :(得分:2)

如果您的输入实际上是一个正确的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-"

答案 1 :(得分:0)

您可以使用var data: PByte; read, bytesRead: Integer; Size: DWORD; //... data := PByte(AllocMem(Size)); bytesRead := 0; repeat read := recv(Sock, data + bytesRead, Size - Cardinal(bytesRead), 0); if read <= 0 then begin Writeln('0 received, exiting...'); Exit; end; bytesRead := bytesRead + read; until DWORD(bytesRead) = Size; ,在第一个块中删除前导空格。在第二个块中,如果看到包含“名称”的行,则将其存储到名为awk的变量中,然后如果以下一行之一包含name,则打印先前捕获的变量{{1} }和当前行。

English

答案 2 :(得分:0)

另一个awk,仅进行一点点格式检查

$ awk '/"name":/         {n=$0} 
       /"Score":/        {s=1} 
       s && /}/          {s=n=""} 
       s && /"English":/ {print n ORS $0}' file | awk '$1=$1'

"name": "ABC",
"English": "A+",
"name": "CDE",
"English": "A-",

检查“分数”元素中是否包含“英语”。

答案 3 :(得分:0)

Sed解决方案:

sed -n 's/^ *//;/name/h;/English/{H;g;p;}'

答案 4 :(得分:0)

$ 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 = $1
    gsub(/^"|"[^"]*$/,"",key)
    f[key] = $0
}
key == "English" {
    print f["name"] ORS $0
}

$ awk -f tst.awk file
"name": "ABC"
"English": "A+"
"name": "CDE"
"English": "A-"

使用以上两种方法,如果将来要打印其他任何内容,例如Age,您只需按照现有模式将其添加到列表中即可。

答案 5 :(得分:0)

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

sed -n '/name/h;/English/!b;H;g;s/^\s*//Mgp' file

使用-n选项打开可选打印。

复制包含name的行。

扔掉不包含English的行。

将包含English的行追加到name的行。

用保留空间的内容替换当前行。

删除任一行开头的空白并打印结果。