![改变角色](https://linux22.com/image/103027/%E6%94%B9%E5%8F%98%E8%A7%92%E8%89%B2.png)
我需要在 600 多个文件中将单引号替换为双引号,并将双引号替换为单引号。我一天大部分时间都在阅读各种主题。我只知道一些基本的 shell 脚本命令并且不熟悉 regexp,这让我感到困惑。
下面是我制作的一个通用的示例文件。
some text KEYWORD_1 table name column = "string" AND column = "string"
Additional text
.
.
.
some text KEYWORD_2 text 'text in quote' etc.
我只想用关键字更改两行的引号。我不能保证关键字始终位于第一行和最后一行。我需要我的解决方案来查找关键字并仅更改该行上的所有引号。
我尝试了在这个论坛上类似问题中找到的一些东西,包括 SED 上的元数据。我试图弄清楚如何使用这个命令:sed -i 's/foo\(.*baz\)/bar\1/' file
。根据该主题,该命令“仅当同一行后面有 baz 时才用 bar 替换 foo”。我的关键字不在同一行后面,而是在开头,我无法让它为我工作。
我也尝试过ex -sc 'g/DEL/s/ALF/BRA/g' -cx file
,没有做任何事情。我假设它无法从命令行执行。我真的不想打开 600 个文件中的每一个。
有一次我尝试过,grep KEYWORD_1 file | sed -i "s/'/\"/g" file
当然,这改变了文件中的所有引号,而不仅仅是一行。
我敢打赌解决方案很简单,只是我看不到它。我怎样才能做到这一点?
根据要求,我想要的输出是:
some text KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
some text KEYWORD_2 text "text in quote" etc.
答案1
改变角色
将一组字符更改为另一组字符通常是该tr
命令的一项任务,但由于您只想在某些行上执行此操作,因此最好使用类似于sed
以下命令的命令来完成:y
tr
sed -e "/^KEYWORD_1/ y/\"/'/" \
-e "/^KEYWORD_2/ y/'/\"/" \
file
这里的每个sed
命令都以行选择器开头/^KEYWORD/
,指示sed
仅对与 之间的模式匹配的行进行操作/
。这里的模式以字符开头^
,表示它们位于行的开头。
行选择器后面是sed
替换命令y/set1/set2/g
,它将每个出现的字符替换为set1
在 中具有相同位置的字符set2
。
交换字符
现在,如果您想在同一行上将每个替换"
为'
,并且同时将每个'
替换为"
,则只能使用一个命令:
sed -e "/^KEYWORD_1\|^KEYWORD_2/ y/\"'/'\"/" file
答案2
这里的复杂之处在于,如果您将 all 替换'
为"
,然后将 all "
with替换'
,那么您将只剩下 only '
。因此,您首先需要替换'
为其他内容(例如,\0
您可以放心地假设它不会出现在输入文件中的 NULL 字符 ( )),然后"
再次'
替换为其他内容"
。例如,在 Perl 中:
$ perl -pe "if(/KEYWORD/){s/'/\0/g; s/\"/'/g; s/\0/\"/g}" file
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
解释
-pe
:p应用 给出的脚本后打印每个输入行-e
。if(/KEYWORD/){something}
something
:仅当该行匹配时才执行KEYWORD
。s/foo/bar/g
foo
:将行中所有出现的 替换为bar
。意思g
是“全球”。如果没有它,则只会替换每行中第一个出现的位置。
请注意,由于脚本本身位于双引号内,因此脚本内的双引号需要转义(\"
)。
正如评论中指出的,我首先应该想到一种更直接的方法:
perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file
运算tr
符音译字符列表。一般格式为tr/searchlist/replacementlist/
.因此,这将替换 all'
和"
all"
只'
在匹配的行上KEYWORD
。
答案3
有点粗糙,但可以使用 GNU awk:
$ awk -v sq="'" '/KEYWORD/{if ($0~sq){ gsub(sq,"\"")} else if ($0~"\"") gsub(/\"/,sq)};1' input.txt
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
.
.
.
KEYWORD_2 text "text in quote" etc.
sq 变量用于表示单引号,因为将其嵌入到代码块本身在 awk 中有点痛苦。基本思想是我们搜索模式,如果找到模式 - 我们决定替换什么。 Final 1
只是告诉 awk 打印这些行。
至于将其输出到文件,只需使用shell的>
运算符将文本重定向到临时文件,并通过命令用新文件替换旧文件mv
。