首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当试图添加一些文本时,Sed变量展开和\n匹配

当试图添加一些文本时,Sed变量展开和\n匹配
EN

Stack Overflow用户
提问于 2020-01-08 15:50:49
回答 3查看 236关注 0票数 0

我有以下模板文件

代码语言:javascript
复制
# 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 (这是必需的,我不能使用其他工具)

代码语言:javascript
复制
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

我尝试使用以下命令:

代码语言:javascript
复制
sed "/# INSERT YOUR OWN RULE/aTEXTTOAPPEND" test.txt

结果:

代码语言:javascript
复制
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
TEXTTOAPPEND
#

旧代码使用perl来完成这项工作。

代码语言:javascript
复制
perl -i -0pe 's/(#( |\t)*\n# INSERT YOUR OWN RULE.*\n#( |\t)*\n)/\1\n'"$REPLACE"'\n/g' /etc/squid/squid.conf

我面临两个问题:

1-无法在此附加命令中使用varible

我已经试过了:

代码语言:javascript
复制
$ 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-不能在我想要附加文本的行后面匹配散列字符(当我添加命令停止匹配时,在本例中没有添加任何内容)

代码语言:javascript
复制
sed "/# INSERT YOUR OWN RULE.*\n#/aTEXTTOAPPEND" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

预期产出:

代码语言:javascript
复制
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
TEXTTOAPPEND

有人能指出我在这里错过了什么吗?对于变量展开,我认为使用双引号和${var}可以完成任务。

更新:

我使用git-bash尝试了所有的东西,在真正的linux机器中,下面的命令起了作用:

代码语言:javascript
复制
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?

代码语言:javascript
复制
sed "/# INSERT YOUR OWN RULE.*\n#.*/a${REPLACE}" test.txt
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-08 16:31:04

有人能指出我在这里错过了什么吗?

sed中的命令用换行符分隔。Sed看到一个换行符-它假设命令在这里结束。我可以用带有换行符的简单变量再现sed: -e expression #1, char 53: unknown command: 'B',下一行以B开头。

代码语言:javascript
复制
replace="something
B something"
sed "/# INSERT YOUR OWN RULE/a${replace}"

sed看到asomething并将something追加到输出中,换行符终止a命令。然后它将看到B something并尝试将其解析为命令,但B无效。

使用sed添加变量内容的最安全方法是使用带有r命令的临时文件。注意,您需要在文件名之后使用r命令后的换行符,因为任何;都将被解析为文件名的一部分!在bash中,您可以聪明地将进程替换与这里的字符串组合起来,以创建临时文件描述符*。要输出当前模式空间并将下一行读入sed中的模式空间,请使用n命令。如下所示:

代码语言:javascript
复制
sed '/# INSERT YOUR OWN RULE/{n;r'<(cat <<<"$replace")$'\n}'

它将在regex之后的下一行之后追加replace的内容。注意,在r之后有$'\n' --一个换行符。

*只是一个<(echo "$replace")也能工作,但我觉得cat <<<"$replace"在大字符串的内存消耗方面会更好,我没有以任何方式检查。

以下脚本:

代码语言:javascript
复制
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}'

关于repl的输出

代码语言:javascript
复制
#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一次读一行。因为这是非常相似的,我只想指出我昨天做的这个答案处理同样的问题。sed中的脚本需要使用N命令一次缓冲两行:

代码语言:javascript
复制
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
'

但是您不能使用rsomethingasomethingsed -z进行操作,因为这样记录将以零分隔,因此sed读取整个文件,因此asomething将显示在整个文件之后。好的,您可以测试它sed -z '/# INSERT YOUR OWN RULE.*\n#.*/r'<(cat <<<$replace),它只会在文件的末尾打印$replace的内容。

票数 1
EN

Stack Overflow用户

发布于 2020-01-08 20:58:38

代码语言:javascript
复制
sed "/INSERT YOUR OWN RULE/a '\n'TEXTTOAPPEND" file-for-change |
sed "/INSERT YOUR OWN RULE/{n;s/'/#/;n;s/^'//;n;d"}

第二个sed用于更改和删除下面两行开头的"'“前导符号。

或者,更简单的变体:

代码语言:javascript
复制
sed -r '/INSERT YOUR/,+1{s/(#$)/\1\nTEXTTOAPPEND/}'

它适用于GNU。

票数 0
EN

Stack Overflow用户

发布于 2020-01-09 08:46:15

有时候最简单的方法是最好的,也许就是这样?

代码语言:javascript
复制
sed '8aTEXTTOAPPEND' -i test.txt

这将在第8字符串之后添加'TEXTTOAPPEND‘.

并自动完成此操作

代码语言:javascript
复制
N=$(grep -n 'INSERT YOUR OWN RULE' test.txt) # get line number
N=${N%%:*}                                   # remove all except line number
((N++))                                      # inc line number coz we got this line with #
sed "${N}aTEXTTOAPPEND" -i test.txt          # add text after $Nth line

龙舌兰

代码语言:javascript
复制
N=$(grep -n 'INSERT YOUR OWN RULE' test.txt); N=${N%%:*}; ((N++)); sed "${N}aTEXTTOAPPEND" -i test.txt
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59649422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档