我有外壳命令:
printf '/^PermitRootLogin/\nc\nPermitRootLogin no\n.\nw\nq\n' | ed -s /etc/ssh/sshd_config
我需要在句子中使用此短语捕获#PermitRootLogin
类似PermitRootLogin
但未注释的段落,我正在使用 ed 文本编辑器并尝试找到某种方法来捕获命令中使用一个 RegExp 的所有出现情况。
我在这个操作系统上没有 GNU utils。谢谢你的答案!
答案1
正则表达式与 shell glob 模式不同。 ^?
作为正则表达式没有有效的含义,因为^
匹配行首并且?
表示前面的子表达式的 0 或 1(在本例中为^
)。
尝试这个:
grep `^.?SomeString`
解释:
^ anchors the match to the start of the line
.? means 0 or 1 of any character
SomeString match "Somestring"
答案2
A,我, 和C是独立的命令;它们后面必须有文字在下一行。所以,你需要在之后换行C。你已经得到了\
;看来您只是忘记了n
。
printf '/^PermitRootLogin/\nc\nPermitRootLogin 否\n。\nw\nq\n' | ed -s /etc/ssh/sshd_config ↑
答案3
- 选择一个永远不会出现在配置文件中的任意字符串。最好避免使用
/
、.
、*
和[
等特殊字符]
。例如,我将使用<G-Man>
. 请执行下列操作:
ed -s /etc/ssh/sshd_config << EOF g/^#*PermitRootLogin/s/^/<G-Man>/ g/^<G-Man>##*PermitRootLogin...../s/<G-Man>// 1,$s/^<G-Man>\(#*PermitRootLogin\).*/\1 no/ w q EOF
这是做什么的?
它找到每一行
- 开头为
PermitRootLogin
, 或 - 以一个或多个
#
字符开头,紧接着PermitRootLogin
最多四个其他字符,
并将其更改为
PermitRootLogin no
,将任何#
字符保留在行首。- 开头为
啊?什么?为什么要这样做?
目标是改变以下任意一行:
PermitRootLogin yes PermitRootLogin no PermitRootLogin The quick brown fox jumps over the lazy dog. #PermitRootLogin yes #PermitRootLogin no
但不是以下几行:
#In this section we set #PermitRootLogin to “maybe”, #because we haven’t decided yet.
这种设计可能有一个不幸的副作用,即以下几行:
##PermitRootLogin yes ##PermitRootLogin ???
将要进行更改,并添加以下行:
PermitRootLogin yes # PermitRootLogin yes #PermitRootLogin yes
将不会。
- 它是如何工作的?
g/^#*PermitRootLogin/s/^/<G-Man>/
查找所有以 开头PermitRootLogin
,或以一个或多个#
字符开头,紧随其后的行PermitRootLogin
,并用字符串“标记”它们<G-Man>
(将其插入行的开头)。这将影响注释掉的行,前提是字符PermitRootLogin
之前或之后没有空格(或其他任何内容) 。#
g/^<G-Man>##*PermitRootLogin...../s/<G-Man>//
查找所有带有标签的行最后一个#
开头,之后至少五个字符PermitRootLogin
,并删除标签。这会取消PermitRootLogin
长度超过 的注释行的标记yes
。 (当然你可以改变数量.
如果你愿意的话。)1,$s/^<G-Man>\(#*PermitRootLogin\).*/\1 no/
查找仍带有标记的所有行,删除标记,捕获PermitRootLogin
和所有前面的#
字符,保留它们,并将该行的其余部分替换为no
。
- 当然,
printf
如果您愿意,您可以将这些命令折叠到 a 中。