我陷入了困境。我有一个包含内容的文件 script.txt
$cat script.txt
SET TABLESPACE CONTAINERS FOR 3
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data2/dbs/rahtest/rahtest1.lrg' 5120
);
SET TABLESPACE CONTAINERS FOR 4
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data2/dbs/rahtest/rahtest2.lrg' 5120
);
我的要求是行中的文件系统
FILE '/db2data2/dbs/rahtest/rahtest1.lrg' 5120
FILE '/db2data1/dbs/rahtest/rahtest2.lrg' 5120
我需要更换
/db2data2/dbs/rahtest/rahtest1.lrg
和
/db2data2/dbs/rahtest/rahtest2.lrg
与其他文件系统;说
/db2data3/dbs/rahtest/rahtest1.lrg
和
/db2data3/dbs/rahtest/rahtest2.lrg
分别。
其他部分应该是一样的。我的输出现在是这样的——
FILE '/db2data3/dbs/rahtest/rahtest1.lrg' 5120
FILE '/db2data3/dbs/rahtest/rahtest2.lrg' 5120
它应该反映在我的文件中。我不知道线条在线条中的位置。我尝试使用 sed。我尝试将这些行放入变量 var1 和 var2 中
var1=`echo /db2data2/dbs/rahtest/rahtest1.lrg'
var2=`echo /db2data2/dbs/rahtest/rahtest2.lrg'
var3=`echo /db2data3/dbs/rahtest/rahtest1.lrg'
var4=`echo /db2data3/dbs/rahtest/rahtest2.lrg'
当我尝试做的时候
sed 's/$var/$var3' script.txt
它失败,因为 / 在那里。我正在使用 AIX。我的最终文件应该是这样的——
SET TABLESPACE CONTAINERS FOR 3
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data3/dbs/rahtest/rahtest1.lrg' 5120
);
SET TABLESPACE CONTAINERS FOR 4
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data3/dbs/rahtest/rahtest2.lrg' 5120
);
答案1
当文本中存在 a 时,/
您可以使用不同的字符,例如 a|
作为 sed 参数的分隔符。另外,使用变量时,您需要""
在命令中使用双引号 ( ),sed
因为变量不会在单引号内展开。尝试这个:
var1='/db2data2/dbs/rahtest/rahtest1.lrg'
var2='/db2data2/dbs/rahtest/rahtest2.lrg'
var3='/db2data3/dbs/rahtest/rahtest1.lrg'
var4='/db2data3/dbs/rahtest/rahtest2.lrg'
sed -e "s|$var1|$var3|g" -e "s|$var2|$var4|" script.txt
答案2
为了稳健地处理正则表达式中的变量信息,您需要转义正则表达式元字符。这个问题已经被回答过很多次了——我自己也做过很多次——但无论如何,这里是内幕:
^$*[]\.
^这些是基本的正则表达式元字符。其中每一个在正则表达式中都有特殊含义,如下所示句法并且不按字面解释。其中几个的重要性实际上取决于位置,因此有时您可能在没有适当转义的情况下将它们包含在正则表达式中,但这并不意味着你应该- 尤其是当正则表达式由未经验证的输入构成时。
但还有更多:
delimiter newline &
^这些是sed
s///
替代替换语法字符。传统上的分隔符/
是可变的,并且会自动将其解释为新命令的sed
第一个字符。s
换行符 - 位于左侧正则表达式声明的侧面 - 确实是不可避免的。那里是无效的。替换换行符的唯一方法是使用\n
转义符 - 但唯一的方法是得到可能在正则表达式中找到的模式空间中的换行符是您自己放一个换行符 - 因此这通常不是问题。在替换的右侧s///
-代替side - 换行符是可转义的 - 像其他所有一样 - with \
,这是转义元字符。对于 也是如此&
。
因此,要构建一个强大的sed
变量脚本,您需要转义它。这是唯一的办法。因为您预计语句中可能存在分隔符而更改分隔符并不是一种可靠的方法。要么验证输入并排除任何语法错误的可能性,要么转义语法字符以表示您想要的含义。这是编写健壮程序的两种方法——没有其他方法。
幸运的是,sed
这让事情变得非常容易。如前所述 -\
反斜杠是转义元字符,当加倍时甚至会转义自身。这样我们就可以利用sed
来逃避sed
。
printf %s\\n "$regex_field" "$replace_field" |
sed -ne'h;n' -e's|[\&/]|\\&|g' \
-ex -e's|[]/\.$^*[]|\\&|g' \
-eG -e's|\(.*\)\n\(.*\)|s/\1/\2/|p' |
sed -f- edit_file
看?输入在换行符上分隔 - 因此,正如所写,不允许在任何一个中使用换行符$regex_field
或者 $replace_field
。你可以也可以处理这个问题,但是这不会,因此输入的期望将被验证以排除它。
在任何情况下,输入行都会成对地输入第一行sed
,并且当它转义与 a 的右侧相关的字符时,它h
会保存每对行的前半部分的副本并跳到第二行。替代声明。然后,它会更改其保留和模式空间并转义左侧,然后将 RHS 附加到 LHS,并由ewline 分隔符分隔。它要做的最后一件事是在将转义命令打印到标准输出之前添加这些位。n
sed
s///
x
G
\n
s///
p
第二个sed
读取其脚本文件-
(通常被解释为标准输入,但您可能想尝试/dev/fd/0
如果没有,您可能想尝试)然后将该脚本应用于其命名的edit_file
。