如何仅替换某些行上的字符?

Emi*_*fer 5 sed text-processing

我需要在 600 多个文件中用双引号和双引号替换单引号。我一天中的大部分时间都在阅读各种主题。我只知道一些基本的 shell 脚本命令并且不熟悉正则表达式,这使我受到了阻碍。

下面是我制作的有点通用的示例文件。

   some text KEYWORD_1 table name column = "string" AND column = "string"
    Additional text
          .
          .
          .
   some text KEYWORD_2 text 'text in quote' etc. 
Run Code Online (Sandbox Code Playgroud)

我只想用关键字更改 2 行的引号。我不能保证关键字总是第一行和最后一行。我需要我的解决方案来查找关键字并仅更改该行上的所有引号。

我尝试了一些我在这个论坛上的类似问题中找到的东西,包括关于 SED 的元数据。我试图找出如何使用这个命令:sed -i 's/foo\(.*baz\)/bar\1/' file。根据该主题的命令,“仅当同一行后面有 baz 时,才将 foo 替换为 bar。” 我的关键字不在开头的同一行后面,我无法让它为我工作。

我也试过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.
Run Code Online (Sandbox Code Playgroud)

xhi*_*nne 6

改变字符

将一组字符更改为另一组字符通常是tr命令的任务,但由于您只想在某些行上执行此操作,因此最好sed使用y类似于以下命令的命令tr

sed -e "/^KEYWORD_1/  y/\"/'/" \
    -e "/^KEYWORD_2/  y/'/\"/" \
    file
Run Code Online (Sandbox Code Playgroud)

sed这里的每个命令都以一个行选择器开始,/^KEYWORD/它指示sed只对匹配/. 这里的模式以字符开头,^表示它们位于行的开头。

在行选择器之后是sed替换命令y/set1/set2/g,它用在set1中具有相同位置的字符替换每个出现的字符set2

交换字符

现在,如果在同一行要替换的每个"具有'和在同一时间'",你可以只用一个命令:

sed -e "/^KEYWORD_1\|^KEYWORD_2/  y/\"'/'\"/" file
Run Code Online (Sandbox Code Playgroud)


ter*_*don 4

这里的复杂之处在于,如果您将 all 替换'",然后将 all "with替换',那么您将只剩下 only '。因此,您首先需要替换'为其他内容\xe2\x80\x94,例如,\\0您可以放心地假设 NULL 字符 ( ) 不会出现在您的输入文件\xe2\x80\x94 中"'然后替换为其他内容再次与"。例如,在 Perl 中:

\n
$ perl -pe "if(/KEYWORD/){s/'/\\0/g; s/\\"/'/g; s/\\0/\\"/g}" file\nKEYWORD_1 table name column = 'string' AND column = 'string'\nAdditional text\n      .\n      .\n      .\nKEYWORD_2 text "text in quote" etc. \n
Run Code Online (Sandbox Code Playgroud)\n

解释

\n
    \n
  • -pe: p在应用 给出的脚本后打印每个输入行-e
  • \n
  • if(/KEYWORD/){something}:something仅当该行匹配时才执行KEYWORD
  • \n
  • s/foo/bar/gfoo:将行中所有出现的 替换为bar。意思g是“全球”。如果没有它,则只会替换每行中第一个出现的位置。
  • \n
\n

请注意,由于脚本本身位于双引号内,因此脚本内的双引号需要转义 ( \\")。

\n
\n

正如评论中指出的,我首先应该想到一种更直接的方法:

\n
perl -pe "tr/'\\"/\\"'/ if /^KEYWORD/" file\n
Run Code Online (Sandbox Code Playgroud)\n

运算tr符音译字符列表。一般格式为tr/searchlist/replacementlist/. 因此,这将替换 all'"all"'在匹配的行上KEYWORD

\n