2016-10-30 200 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"; 
}