linux - 尝试附加一些文本时 Sed 变量扩展和 \n 匹配
问题描述
我有以下模板文件
# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on "localhost" is a local user
#http_access deny to_localhost
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
#http_access allow localnet
#http_access allow localhost
我想使用 sed 在下面的行后面附加一些文本(这是一个要求,我不能使用其他工具)
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
我尝试使用以下命令:
sed "/# INSERT YOUR OWN RULE/aTEXTTOAPPEND" test.txt
结果:
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
TEXTTOAPPEND
#
旧代码使用 perl 来完成这项工作
perl -i -0pe 's/(#( |\t)*\n# INSERT YOUR OWN RULE.*\n#( |\t)*\n)/\1\n'"$REPLACE"'\n/g' /etc/squid/squid.conf
我面临两个问题:
1 - 无法在此附加命令中使用变量
到目前为止我尝试过:
$ echo $REPLACE
TEXTTOAPPEND
$ sed "/# INSERT YOUR OWN RULE/a${REPLACE}" test.txt
sed: -e expression #1, char 53: unknown command: `B'
sed "/# INSERT YOUR OWN RULE/a\${REPLACE}" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
${REPLACE}
#
2 - 在我想附加文本的行之后无法匹配哈希字符(当我添加 \n 命令停止匹配时,因此在这种情况下不添加任何内容)
sed "/# INSERT YOUR OWN RULE.*\n#/aTEXTTOAPPEND" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
预期输出:
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
TEXTTOAPPEND
有人可以指出我在这里缺少什么吗?对于变量扩展,我认为使用双引号和 ${var} 就可以了。
更新:
我正在使用 git-bash 尝试一切,在真正的 linux 机器上尝试时,下面的命令起作用了:
echo $REPLACE
ABC
sed "/# INSERT YOUR OWN RULE.*/a${REPLACE}" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
ABC
#
现在唯一的问题是 2. 在这种情况下如何使用 \n ?
sed "/# INSERT YOUR OWN RULE.*\n#.*/a${REPLACE}" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
解决方案
有人可以指出我在这里缺少什么吗?
中的命令sed
由换行符分隔。Sed 看到一个换行符 - 它假定命令在这里结束。我可以sed: -e expression #1, char 53: unknown command: 'B'
使用具有换行符的简单变量重现您的内容,下一行以B
:
replace="something
B something"
sed "/# INSERT YOUR OWN RULE/a${replace}"
sed
看到asomething
并附something
加到输出和换行符终止a
命令。然后它看到B something
并尝试将其解析为命令,但B
无效。
使用 sed 附加变量内容的最安全方法是使用带有r
命令的临时文件。请注意,您需要r
在文件名之后的命令后加上换行符,因为任何;
内容都将被解析为文件名的一部分!在 bash 中,您可以很聪明地将进程替换与此处的字符串结合起来创建一个临时文件描述符*。在 sed 使用n
命令中输出当前模式空间并将下一行读入模式空间。像这样:
sed '/# INSERT YOUR OWN RULE/{n;r'<(cat <<<"$replace")$'\n}'
它将replace
在正则表达式之后的下一行之后附加内容。请注意,之后r
有$'\n'
- 换行符。
* 只是 a<(echo "$replace")
也可以,但不知何故我觉得cat <<<"$replace"
大字符串的内存消耗会更好,我没有以任何方式检查。
以下脚本:
replace="anything
can
be here!"
cat <<EOF |
#http_access deny to_localhost
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
# Example rule allowing access from your local networks.
EOF
sed '/# INSERT YOUR OWN RULE/{n;r'<(cat <<<"$replace")$'\n}'
#http_access deny to_localhost
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
anything
can
be here!
# Example rule allowing access from your local networks.
在这种情况下如何使用 \n ?
Sed 一次读取一行。由于这非常相似,我只想指出我昨天刚做的这个答案,它处理了同样的问题。N
在这种情况下,sed 中的脚本需要使用命令一次缓冲两行:
sed '
: restart
N # buffer two lines
: loop
# match two lines
/# INSERT YOUR OWN RULE.*\n#/{
r'<(cat <<<"$replace")'
# print and start over
n ; b restart
}
# hold, print leading line, change, remove leading line
h ; s/\n.*// ; p ; x ; s/[^\n]*\n//
# append next line and loop
N
b loop
'
但是你不能做rsomething
or asomething
withsed -z
因为这样记录会被零分隔,所以 sed 读取整个文件,所以asomething
会显示在整个文件之后。好吧,您可以对其进行测试sed -z '/# INSERT YOUR OWN RULE.*\n#.*/r'<(cat <<<$replace)
,它只会$replace
在文件末尾打印 的内容。
推荐阅读
- flask - wtforms TextAreaField 的活动字符数
- javascript - 卸载组件时,一个特定的道具未定义
- haskell - Haskell 详细记忆类型签名
- php - PHP 链式类方法与其他类合并
- redis - Kubernetes集群中如何连接redis-ha集群?
- excel - 根据 2 个条件查找和连接字符串
- angular - ngFor over Array of Observables
- aframe - A-Frame 0.9.0 中的手控组件支持
- octave - sum elements of vector excluding the first element in Octave
- javascript - Angular在构建时没有嵌入所有脚本