在一个非常大的文件上替换字符串
String replace on a very large file
我有一个巨大的文本文件 JSON。你可以在这里看到它:http://api.mtgdb.info/cards/。我已将此 JSON 保存到名为 cards.json
.
的文件中
在 cards.json
中,我需要用反斜杠 \
转义每个单引号 '
。
所以我需要用\'
替换'
。
通常这在任何编辑器中都是微不足道的,但是文件太大了。 如何转义此字符串中的所有单引号?
我试过的:
我尝试使用 sed
。我的命令是 sed s/\'/\\'/ cards.json > cards_cleaned.json
。然而 cards_cleaned.json 文件没有任何转义 '
,它只是 cards.json
的精确副本。 Sed 在我执行 sed s/\'/foobar/ cards.json > cards_cleaned.json
时工作,所以我假设我的转义反斜杠有问题。
我尝试使用 vim
。我在 vim $ vi cards.json
中打开了 cards.json。然后我尝试使用 :%s/'/\'/g
进行全局字符串替换。这并没有改变文件中的任何内容。
在 Vi 中,您需要转义 \ 字符。
尝试使用
:%s/'/\'/g
对我来说很有效。
Test.txt
\'\'\' \'\'\'
sed "s/'/\\&/g" cards.json > cards_cleaned.json
- 无需在搜索模式中进行第一次转义
\'
- 你应该用双引号括起来(如果单引号不是要更改的字符,则为单引号)并转义由于在这种情况下 shell 级别使用的双引号
你需要双重逃避backelas,所以使用:
sed -i.bak "s/'/\\'/g" cards.json
您需要在 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.
的上下文中是特殊的
你可以这样使用,在vim。
:%s/'/\\'/g
在 sed 中,
sed "s/'/\\'/g" filename
这是一个 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\'
虽然@anubhava 或@gboffi 的答案有效,但它们会产生 INVALID JSON.
JSON allows only backslash
:
后的几个字符
\"
\
\/
\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
有一些问题。在编辑之前,您可以 pretty print(折叠和缩进)JSON。这里有很多工具,我使用的是 JSON_XS perl 包中的 json_xs
命令。在 "prettyfying" 之后你可以安全地使用 vim
。
我有一个巨大的文本文件 JSON。你可以在这里看到它:http://api.mtgdb.info/cards/。我已将此 JSON 保存到名为 cards.json
.
在 cards.json
中,我需要用反斜杠 \
转义每个单引号 '
。
所以我需要用\'
替换'
。
通常这在任何编辑器中都是微不足道的,但是文件太大了。 如何转义此字符串中的所有单引号?
我试过的:
我尝试使用
sed
。我的命令是sed s/\'/\\'/ cards.json > cards_cleaned.json
。然而 cards_cleaned.json 文件没有任何转义'
,它只是cards.json
的精确副本。 Sed 在我执行sed s/\'/foobar/ cards.json > cards_cleaned.json
时工作,所以我假设我的转义反斜杠有问题。我尝试使用
vim
。我在 vim$ vi cards.json
中打开了 cards.json。然后我尝试使用:%s/'/\'/g
进行全局字符串替换。这并没有改变文件中的任何内容。
在 Vi 中,您需要转义 \ 字符。
尝试使用
:%s/'/\'/g
对我来说很有效。
Test.txt
\'\'\' \'\'\'
sed "s/'/\\&/g" cards.json > cards_cleaned.json
- 无需在搜索模式中进行第一次转义
\'
- 你应该用双引号括起来(如果单引号不是要更改的字符,则为单引号)并转义由于在这种情况下 shell 级别使用的双引号
你需要双重逃避backelas,所以使用:
sed -i.bak "s/'/\\'/g" cards.json
您需要在 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.
你可以这样使用,在vim。
:%s/'/\\'/g
在 sed 中,
sed "s/'/\\'/g" filename
这是一个 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\'
虽然@anubhava 或@gboffi 的答案有效,但它们会产生 INVALID JSON.
JSON allows only backslash
:
\"
\
\/
\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
有一些问题。在编辑之前,您可以 pretty print(折叠和缩进)JSON。这里有很多工具,我使用的是 JSON_XS perl 包中的 json_xs
命令。在 "prettyfying" 之后你可以安全地使用 vim
。