【问题标题】:String replace on a very large file对一个非常大的文件进行字符串替换
【发布时间】:2015-05-19 13:48:38
【问题描述】:

我有一个巨大的 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 进行全局字符串替换。这并没有改变文件中的任何内容。

【问题讨论】:

  • 为什么需要一个反斜杠?正如您在 jm666 帖子中看到的,这给出了无效的 json 代码。

标签: regex bash vim sed


【解决方案1】:

在 Vi 中,您需要转义 \ 字符。

尝试使用

:%s/'/\\'/g

对我来说它有效。

Test.txt

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

【讨论】:

  • 这适用于测试,但 vim 永远不会完成操作。
  • 您可以在 sed 中使用不同的分隔符:cat cards.json | sed "s_'_/'_g" > cards.json.clean
【解决方案2】:
sed "s/'/\\\\&/g" cards.json > cards_cleaned.json
  • 不需要你的第一个转义搜索模式\'
  • 您应该用双引号括起来(如果单引号不是要更改的字符,则使用单引号)并由于在这种情况下在 shell 级别使用双引号而转义转义

【讨论】:

  • 您的答案与我的 non working 示例相对应,所以我想它可能会遇到与我演示的相同的问题...
  • $ echo "eoieriou'iouou'oiuiouiuo" | sed "s/'/\\&'/g" 回馈eoieriou&iouou&oiuiouiuo,因为执行的sed 命令是s/'/\&/g(请注意,我没有反对,但您可以在发布之前测试您的答案,不能不是吗?)
  • @gboffi 事件如果你还没有投反对票,你的回复值得(我赞成你对此的评论)。我适应双重双重转义,我尽量避免使用&
【解决方案3】:

你需要双重转义 backelas,所以使用:

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

【讨论】:

  • 它也适用于三个“\”:sed -i.bak "s/'/\\\'/g" cards.json
  • @Jotne 是的,它有效,但我很难向我解释它为什么有效......,我想知道你是否愿意在单独的答案中解释它为什么有效跨度>
  • @gboffi 我不知道为什么,只是测试了一下。没有错误,并且输出正确。
  • @Jotne 似乎序列 \' 在被双引号引用时被 shell 解释不同,就像在产生以下输出的 $ echo \' "\'" 中一样:' \' --- 我仍然有找到真正的解释......也许改天,ciao
【解决方案4】:

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

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

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

我们必须在反斜杠到达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 上下文中是特殊的。

【讨论】:

    【解决方案5】:

    你可以像这样在 vim 中使用。

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

    在 sed 中,

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

    【讨论】:

      【解决方案6】:

      这是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\\'
      

      【讨论】:

        【解决方案7】:

        虽然@anubhava 或@gboffi 的答案有效,但它们会生成INVALID JSON。

        JSON allows onlybackslash 后面的几个字符:

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

        例如以下原始(正确)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 命令。在“美化”之后,您可以安全地使用vim

        【讨论】:

        • 但是,如果 OP 通过另一个程序解析这个问题,该程序会导致单引号出现问题并且转义会有所帮助,因为它在过程中被删除并保留单引号?
        • @Jotne - 猜测。无论如何,(如您所见)我为两者都提供了解决方案。
        • 是的,纯属猜测。这只是对无效 Json 的评论。只要 OP 不评论什么是有效的,什么是无效的,我们就必须拭目以待。我可能是 OP 要求一个斜杠而不是两个斜杠的原因。
        • @jm666 您的评论是明智的,但作为 jotne,您不能自己推测文件的目的地。 (你们俩+1)
        • @NeronLeVelu 因此我在我的原始答案中包含了 both 场景的解决方案,现在将其编辑为粗体(当然)。 :)
        猜你喜欢
        • 2016-05-01
        • 2012-11-25
        • 1970-01-01
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-15
        • 2011-07-01
        相关资源
        最近更新 更多