2016-10-30 69 views
1

我必须修改文件json。我必须用双引号替换单引号,但我不能使用以下命令sed -i -r "s/'/\"/g" file,因为在文件中有更多单引号不会更改。用括号中的双引号替换单引号

以下代码是串的一个例子:

"categories": [['Clothing, Shoes & Jewelry', 'Girls'], ['Clothing, Shoes & Jewelry', 'Novelty, Costumes & More', 'Costumes & Accessories', 'More Accessories', 'Kids & Baby']] 

的desided结果应该是:

"categories": [["Clothing, Shoes & Jewelry", "Girls"], ["Clothing, Shoes & Jewelry", "Novelty, Costumes & More", "Costumes & Accessories", "More Accessories", "Kids & Baby"]] 

示例文件:

{"categories": [['Movies & TV', 'Movies']], "title": "Understanding Seizures and Epilepsy DVD"}, 
{"title": "Who on Earth is Tom Baker?", "salesRank": {"Books": 3843450}, "categories": [['Books']]}, 
{"categories": [['Clothing, Shoes & Jewelry', 'Girls'], ['Clothing, Shoes & Jewelry', 'Novelty, Costumes & More', 'Costumes & Accessories', 'More Accessories', 'Kids & Baby']], "description": "description, "title": "Mog's Kittens", "salesRank": {"Books": 1760368}}}, 
{"description": "Three Dr. Suess' Puzzles", "brand": "Dr. Seuss", "categories": [['Toys & Games', 'Puzzles', 'Jigsaw Puzzles']]}, 

我使用的正则表达式,但问题是我不知道括号中有多少元素。所以我想用一种方法来替换括号中的所有单引号,这是一种完美的方式,但我找不到解决方案。

+0

你的意思是,你只能改变报价在给定的直线?你能发布一个(小)完整的json文件吗? –

+0

{“categories”:[[''Movies&TV','Movies']],“title”:“Understanding Seizures and Epilepsy DVD”}, {“title”:“地球上的谁是汤姆贝克?”, salesRank“:{”Books“:3843450},”categories“:[['Books']]}, {”categories“:[['Clothing,Shoes&Jewelry','Girls'],['Clothing,Shoes &'Jewelry','Novelty,Costumes&More','Costumes&Accessories','More Accessories','Kids&Baby']],“description”:“description”,“title”:“Mog's Kittens”,“salesRank “:{”Books“:1760368}}}, {”description“:”三个Suess博士拼图“,”brand“:”Dr.Seuss“,”categories“:[['玩具和游戏','拼图','拼图']]}, – Nanan

+0

对不起,很难读...但如果你看到字段”类别“,我会改变在双引号中使用单引号......但是在该字段中有不同数量的字符串 – Nanan

回答

0

我找到了一种方法来使用python。

请注意,由于单引号(还有一些复制/粘贴问题,缺少引号,我修正了这个问题),您提供的json流无法被python json识别。

我的解决方案是完全使用python库,我怀疑你可以用sed做同样的事情,这就是为什么我提供它,尽管你没有提到这个技术。

  • 我使用ast.literal_eval读取数据,因为它是一个精确的Python语法的字典列表。单引号不是问题ast
  • 我使用json.dump写入数据。它使用双引号写入数据。
  • 请注意,我把它写在一个“假”文件中(即用I/O写入方法来“愚弄”json串行器的字符串)。

这里有一个独立的片断,它的工作原理:

import io 

foo = """[{"categories": [['Movies & TV', 'Movies']], "title": "Understanding Seizures and Epilepsy DVD"}, 
{"title": "Who on Earth is Tom Baker?", "salesRank": {"Books": 3843450}, "categories": [['Books']]}, 
{"categories": [['Clothing, Shoes & Jewelry', 'Girls'], ['Clothing, Shoes & Jewelry', 'Novelty, Costumes & More', 'Costumes & Accessories', 'More Accessories', 'Kids & Baby']], "description": "description", "title": "Mog's Kittens", "salesRank": {"Books": 1760368}}, 
{"description": "Three Dr. Suess' Puzzles", 
"brand": "Dr. Seuss", "categories": [['Toys & Games', 'Puzzles', 'Jigsaw Puzzles']]} 
]""" 

fp = io.StringIO() 

json_data=ast.literal_eval(foo) 
json.dump(json_data,fp) 
print(fp.getvalue()) 

结果:

[{"categories": [["Movies & TV", "Movies"]], "title": "Understanding Seizures and Epilepsy DVD"}, {"salesRank": {"Books": 3843450}, "categories": [["Books"]], "title": "Who on Earth is Tom Baker?"}, {"description": "description", "salesRank": {"Books": 1760368}, "categories": [["Clothing, Shoes & Jewelry", "Girls"], ["Clothing, Shoes & Jewelry", "Novelty, Costumes & More", "Costumes & Accessories", "More Accessories", "Kids & Baby"]], "title": "Mog's Kittens"}, {"brand": "Dr. Seuss", "description": "Three Dr. Suess' Puzzles", "categories": [["Toys & Games", "Puzzles", "Jigsaw Puzzles"]]}] 

这里有一个完整的脚本服用2个参数(输入文件&输出文件),并执行转换。您可以将现有的bash脚本中使用这个脚本,如果你不舒服与Python(保存在fix_quotes.py为例):

import ast,json,sys 

input_file = sys.argv[1] 
output_file = sys.argv[2] 

with open(input_file,"r") as fr: 
    json_data=ast.literal_eval(fr.read()) 
with open(output_file,"w") as fw: 
    json.dump(json_data,fw) 
+0

有趣!我使用[sed],因为我必须改变的文件非常大......但是我找不到解决方案,所以我接受其他解决方案......如果我使用json文件而不是字符串,这会起作用吗?我的意思是,有一个函数可以加载文件以使用此解决方案? – Nanan

+0

非常感谢,这是我正在寻找的解决方案......最后一件事,如果我试图用一个非常大的文件来做,我可以最终执行?大声笑 – Nanan

+0

最后给出了独立的例子。如果文件超出机器内存(实际低于该限制),则会因数据一次加载而失败。请注意,我在开始和结尾添加了方括号,以便能够将其作为字典列表进行处理。可以想象一次加载1行(放下方括号)并一次写入1行(一次一个字母)。 –

1
#!/usr/bin/perl -w 
use strict; 

# read each line from stdin 
while (my $l=<>) {  
    chomp($l); # remove newline char 

    # split: get contents of innermost square brackets 
    my @a=split(/(\[[^][]*\])/,$l); 

    foreach my $i (@a) { 
     # replace quotes iff innermost square brackets 
     if ($i=~/^\[/) { $i=~s/'/"/g; } 
    } 

    # join and print 
    print join('',@a)."\n"; 
}