2016-11-01 54 views
2

我试图删除线与现有线路的最后一个字符用的sed:如何删除前行的最后一个字符用sed的

我有一个JSON文件:

{ 
"name":"John", 
"age":"16", 
"country":"Spain" 
} 

我想删除所有条目的国家,为此我必须删除前一行的json语法的逗号。

我使用这个模式:

sed '/country/d' test.json 
sed -n '/resolved//.$//{x;d;};1h;1!{x;p;};${x;p;}' test.json 

编者按
的OP后来澄清了以下额外要求,这无效现有的一些答案:
- 发生的country属性应删除
- 所有级别的对象层次
- 空白的差异应该被容忍

+4

我想知道为什么'sed'? 有很多能够解析JSON的工具。考虑使用'jq','perl','php',或者内置JSON解析器的东西。 –

+0

我更喜欢SHELL,因为我将在jenkins工作中使用该命令。 –

+1

“我更喜欢SHELL”:有些工具可以用来从shell脚本操作json。例如jq。 – njzk2

回答

2

使用正确的JSON解析器如jq一般最好的选择 e(见下文),但如果安装实用程序不是一个选项,请尝试此操作GNUsed命令

$ sed -zr 's/,\s*"country":[^\n]+//g' test.json 
{ 
"name":"John", 
"age":"16" 
} 
  • -zNUL s,这在此情况下意味着,整个文件被读取一次,这使交叉线替换将输入到记录。

  • -r使扩展正则表达式为更多现代语法与更多的功能。

  • s/,\n"country":\s*//g替换逗号出现的所有随后空格组成的(可能为空)运行(可能包括一个换行),然后通过"country"该行的与空字符串,即端,实际上删除了匹配的字符串。

    • 注意,这假定没有其它属性或关闭}如下例如在同一行上一个country属性。

为了证明基于jq一个更可靠的解决方案。

Bertrand Martel's helpful answer包含在输入对象分层结构的任何地方替换country属性的jq溶液,其中,但是,并没有解决的要求(加入)。

jq更高尚未发布的版本比v1.5.2,一个内置walk/1功能将可用,可实现以下简单的解决方案:

# Walk all nodes and remove a "country" property from any object. 
jq 'walk(if type == "object" then del (.country) else . end)' test.json 

v1.5.2及以下,你可以定义walk自己的简化字:

jq ' 
    # Define recursive function walk_objects/1 that walks all objects in the 
    # hierarchy. 
    def walk_objects(f): . as $in | 
    if type == "object" then 
     reduce keys[] as $key 
     ({}; . + { ($key): ($in[$key] | walk_objects(f)) }) | f 
    elif type == "array" then map(walk_objects(f)) 
    else . end; 
    # Walk all objects and remove a "country" property, if present. 
    walk_objects(del(.country)) 
' test.json 
+0

这是只适用于第一个关键,而不是所有的休息,我有多个条目与国家键 –

+0

@YasserB .:只需添加'g'选项来全局替换(_all_ occurrences) - 查看我的更新。 – mklement0

+0

谢谢whatif在“国家”之前有空间 –

1

您可以使用JSON解析器像jq解析JSON文件。下面将在result.json返回文档没有country场和写入新文件:

jq 'del(.country)' file.json > result.json 
+0

这不适用于多个/嵌套密钥 –

+0

@YasserB。你的json文件没有多个或嵌套的键。 – njzk2

+0

检查这个要点:https://gist.github.com/akinaru/120cb4583b60b0dc77f1012bc5f4a9f8为一个完整的例子 –

2

正如指出的之前你真的应该考虑使用JSON解析器来解析JSON。

当那个据说可以发出声音的整个文件,删除新行,然后accordantly更换 :

$ sed ':a;N;$!ba;s/\n//g;s/,"country"[^}]*//' test.json 
{"name":"John","age":"16"} 

击穿:

:a;     # Define label 'a' 
    N;    # Append next line to pattern space 
    $!ba;   # Goto 'a' unless it's the last line 
s/\n//g;   # Replace all newlines with nothing 
s/,"country"[^}]*// # Replace ',"country...' with nothing 
2

这可能为你工作(GNU SED):

sed 'N;s/,\s*\n\s*"country".*//;P;D' file 

将两行读入模式空间并删除替换字符串。

N.B.允许在该行的任何一侧留出空间。

相关问题