字符串替换非常大的文件

时间:2015-03-17 07:58:53

标签: regex bash vim sed

我有一个JSON的巨型文本文件。你可以在这里看到它:http://api.mtgdb.info/cards/。我已将此JSON保存到名为cards.json的文件中。

cards.json中,我需要使用反斜杠'来转义每个引用\

所以我需要将'替换为\'

通常这在任何编辑器中都是微不足道的,但是文件太大了。 如何在此字符串中转义所有单引号?

我尝试了什么:

  1. 我尝试使用sed。我的命令是sed s/\'/\\\'/ cards.json > cards_cleaned.json。但是,cards_cleaned.json文件没有任何转义',它只是cards.json的精确副本。当我做sed s/\'/foobar/ cards.json > cards_cleaned.json时,Sed工作,所以我假设我的逃避反斜杠有问题。

  2. 我尝试使用vim。我在vim $ vi cards.json打开了cards.json。然后我尝试使用:%s/'/\'/g进行全局字符串替换。这没有改变文件中的任何内容。

7 个答案:

答案 0 :(得分:2)

你需要在shell中使用双引号来避免引用单引号字符,但是你必须要小心,因为对于双引号字符串,shell使用反斜杠作为引用字符

$ echo "eoieriou'iouou'oiuiouiuo"|sed "s/'/\\'/g"
eoieriou'iouou'oiuiouiuo

并且sed尝试执行的命令是s/'/\'/g,但sed引用字符是反斜杠,因此您可以用单引号替换每个单引号...

我们必须在到达sed时引用反斜杠 ,所以让我们试试

$ echo "eoieriou'iouou'oiuiouiuo"|sed "s/'/\\\\'/g"  # Four (4) backslashes in a row
eoieriou\'iouou\'oiuiouiuo
$ 

没关系,不是吗?因为sed被指示执行s/'/\\'/g,所以来自sed的POV的引用字符就是反斜杠本身......

请注意,引号(单引号或双引号)不是sed的POV中的特殊字符,它们仅在shell的上下文中特殊。

答案 1 :(得分:2)

虽然@ anubhava或@ gboffi的答案有效,但他们会产生无效 JSON。

backslash之后

JSON allows only几个字符:

\"
\\
\/
\b
\f
\n
\r
\t
\u four-hex-digits

e.g。以下原始(正确)JSON的部分

[
   {
      "description" : "Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land's controller.",
      "rarity" : "Rare",
      "name" : "Ankh of Mishra"
   }
]

你想要

[
   {
      "description" : "Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land\'s controller.",
      "rarity" : "Rare",
      "name" : "Ankh of Mishra"
   }
]
#e.g. instead of the land's want land\'s

但这是一个无效的JSON。

所以,如果你(由于一些奇怪的原因)想要backslash,你需要使用双\\,例如:

[
   {
      "description" : "Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land\\'s controller.",
      "rarity" : "Rare",
      "name" : "Ankh of Mishra"
   }
]

解决方案(适用于两者)

perl

perl -pE "s/'/\\\'/g" < mtg_cards.json > cards.malformed.json
#changes "land's" to wrong "land\'s"

perl -pE "s/'/\\\\'/g" < mtg_cards.json > card_with_double_BS.json
#changes "land's" to "land\\s"

Ps:因为你的文件只有一行(30MB),vim有一些问题。在编辑之前,您可以漂亮打印(折叠和缩进)JSON。这里有很多工具,我使用JSON_XS perl包中的json_xs命令。在&#34;漂亮&#34;您可以安全地使用vim

答案 2 :(得分:1)

在Vi中你需要转义\ character。

尝试使用

:%s/'/\\'/g

对我而言,它有效。

  

Test.txt的

     

\'\'\'\'\'\'

答案 3 :(得分:1)

你需要双重逃避backelas,所以使用:

sed -i.bak "s/'/\\\\'/g" cards.json

答案 4 :(得分:1)

你可以在vim中使用这样的东西。

 :%s/'/\\\'/g

在sed中,

 sed "s/'/\\\'/g" filename

答案 5 :(得分:1)

以下是awk版本:

cat file
hi'more data here'

awk '{gsub(g,"\\"g)}1' g="'" file
hi\'more data here\'

或者如果你需要双反斜杠:

awk '{gsub(g,"\\\\"g)}1' g="'" file
hi\\'more data here\\'

答案 6 :(得分:-1)

sed "s/'/\\\\&/g" cards.json > cards_cleaned.json
  • 无需首次转义搜索模式\'
  • 你应该用双引号括起来(单引号如果单引号不是要更改的字符)并且因为在这种情况下在shell级别使用双引号而逃避转义