【问题标题】:Replace a line in a text file using sed but keeping \ as part of the replacement line from perl script使用 sed 替换文本文件中的一行,但将 \ 作为 perl 脚本中替换行的一部分
【发布时间】:2017-04-30 06:24:17
【问题描述】:

我需要做的是使用 sed 命令从 perl 替换文件中的一行。问题是我需要放入文件中的行在几个地方都有 \,我还没有想出如何在没有 perl/sed 删除它们的情况下保留 \。

例子是:

system sed "s/^destinaion=.*/destination=Manager {manager hostname\=$NAME,Manager port\=8443} $USER_NAME/" -i /usr/local/example_file.txt;

在我得到的文件中:

destination=Manager {manager hostname=Bill,Manager port=8443} Fred

我需要进入文件:

destination=Manager {manager hostname\=Bill,Manager port\=8443} Fred

这是一个用于配置的属性文件,需要准确。

使用这个网站,我想出了以下适合我的解决方案:

我在 perl 中的命令(只是一个例子):

$VAR1=$NAME

$VAR2=$USER_NAME

$VAR3='destination=Manager {manager hostname\\\\'

$VAR4='Manager port\\\\=8443} '

system sed 's/^destinaion=.*/$VAR3=$VAR1,$VAR4 $VAR2/' -i 
/usr/local/example_file.txt;

输出是:

destination=Manager {manager hostname\=Bill,Manager port\=8443} Fred

这很有效,因为我将同一行传递给 4 个不同的属性文件,具体取决于问题的答案和 redhat 版本。我正在安装的软件具有不同的属性文件,具体取决于所使用的 redhat 版本。我必须通过一次安装来创建属性文件,然后我在脚本中更改属性文件并使用 foreach 在所有服务器上进行安装,这样我就可以运行脚本然后观察错误。

我们目前使用两个版本,因此我必须在脚本中添加 if 语句来选择正确的属性文件。

【问题讨论】:

  • 这很棘手;您必须计算出有多少进程正在解释字符串并删除反斜杠。要将单个反斜杠放入输出中,sed 需要在 s/…/…/ 操作的替换部分中看到两个连续的反斜杠。因为你用双引号括起来,Perl 也有机会解释反斜杠;这意味着您需要在 Perl 中为输出中的每个反斜杠添加 4 个反斜杠。
  • 在 Perl 本身中进行替换通常更快,而无需使用。
  • 不仅更快,更重要的是:更不容易出错。事实上,我很困惑为什么你会想从perl 调用sed,除非你有一个复杂且经过充分测试的sed 脚本可供使用。

标签: linux perl sed


【解决方案1】:

如评论中所述:

这很棘手;您必须计算出有多少进程正在解释字符串并删除反斜杠。要将单个反斜杠放入输出中,sed 需要在 s/…/…/ 操作的替换部分中看到两个连续的反斜杠。因为你用双引号括起来,Perl 也有机会解释反斜杠;这意味着您需要在 Perl 中为输出中的每个反斜杠添加 4 个反斜杠。

因为您在 system 调用中使用了“数组”表示法(除了语法错误——您需要在项目之间使用逗号,并在普通单词周围加上引号),您可以避免让 shell 也解释字符串.

这适用于我在 macOS Sierra 10.12.2 上,并且也适用于 GNU sed(将文件重命名为 data):

#!/usr/bin/perl

use strict;
use warnings;

my $NAME = "Alexander";
my $USER_NAME = "The Great";
system "sed", "-e", "s/^destinaion=.*/destination=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/", "-i.bak", "data";

文件data之前:

##destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred
destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred

文件data之后:

##destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred
destination=Manager {manager hostname\=Alexander,Manager port\=8443} The Great

这是一个变体脚本,它显示了需要不同数量的反斜杠。在连续 8 个反斜杠的示例中,Perl 将数字减半为 4,shell 将数字减半为 2,sed 将 2 解释为输出中的 1。当您连续看到 8 个反斜杠时,您可以确信您没有以最佳方式处理某些事情。 (在过去,troff 文件有时会连续包含 16 个反斜杠,但并不常见,而且很少有人知道为什么需要它们。)

#!/usr/bin/perl

use strict;
use warnings;

my $NAME = "Alexander";
my $USER_NAME = "The Great";
system "sed", "-e", "s/^D1=.*/destination1=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/", "-i.bak", "data";
system "sed -e \"s/^D2=.*/destination2=Manager {manager hostname\\\\\\\\=$NAME,Manager port\\\\\\\\=8443} $USER_NAME/\" -i.bak data";
system "sed -e 's/^D3=.*/destination3=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/' -i.bak data";

这是初始变体数据文件:

D1=Manager {manager hostname=Bill,Manager port=8443} Fred
D2=Manager {manager hostname=Bill,Manager port=8443} Fred
D3=Manager {manager hostname=Bill,Manager port=8443} Fred

这是在变体数据文件上运行变体脚本的结果:

destination1=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
destination2=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
destination3=Manager {manager hostname\=Alexander,Manager port\=8443} The Great

如果您不需要扩展 $NAME$USER_NAME,则可以在数组表示法中的 s/…/…/ 命令周围使用单引号的另一个变体;它只需要两个反斜杠,而不是四个。

【讨论】:

    猜你喜欢
    • 2022-08-13
    • 2017-12-20
    • 2016-05-07
    • 2013-11-01
    • 2020-10-31
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多