我是编程新手(/脚本?),因为这会清楚地表明。
目的:
尝试创建一个可重用的脚本来自动安装/配置新的 linux 实例......因为我不断地破坏它们。在这种情况下,我正在摆弄 /etc/pam.d/sshd
学习... sed 确实让我了解了引号、中断和所有基础知识。
正如你所看到的,我已经让它工作了,但有几个问题(我怀疑有人会指出这种方法是多么脆弱)
问题1-2)
变量文件- 作为参数传递给 sedinsert.sh
sedfind="# Standard Un\*x authentication."
#sedfind=".* Standard Un\*x authentication"
sedinsert="I am a \nmulti line variable \nand I kind of work"
sedfile=sshd
我试图让它完成繁重的工作,即我将转义 sed 命令中所需的任何字符或在此处使用通配符,因为这样我只需在更新时更改变量文件一次,至少对我来说,这是一个干净一点。
它还极大地帮助我的理解,因为我可以轻松地看到变化如何影响输出/结果。
Q1.我在这里引用的内容和新的台词对吗?这似乎可行,但还有其他方法吗?我有一种可怕的感觉,我很快就会遇到一个会打破这个的角色 - 有例子吗?
Q2。是否可以将变量拆分为多行,以便在必要时使该文件更易于使用(例如,类似于在行末尾使用 \ ) - 记住即将出现的 source 和 sed 。
也许脚本中的另一个命令可以处理这个问题? (Grep?或另一个 sed?。
问题2
sedinsert.sh
set -x
source $1
sed -i "\|$sedfind|a\ \n$sedinsert" $sedfile
我试图尽可能保持干净,并且不要在变量周围使用引号。我目前有另一个要替换的,但接下来我可能会考虑将命令作为变量传递
我并不完全同意这个想法,但希望原因是有意义的......即这将用于更改其中包含“困难”字符的各种文件,例如@#“等
问:因此,我必须将第一个新行放在命令本身中(|a\/n....)。如果我不想要它/想要包含多个空行,是否可以通过某种方式将其放入变量本身?
问题3
在 sed 中,您可以将模式分隔符(正确的术语?)从 \ 设置为 | ,这很好。就像我在这里一样。
但每次我认为我找到了一个好用的文件时,我肯定会发现它包含在我查看的下一个文件中
问:是否有一些建议/标准的模糊分隔符在其他地方很少使用 - 所以我不会一直在文件中找到它,例如一些俄语字符(向任何俄罗斯人道歉)而不是#|等。
我只是有点困惑为什么每个人都使用常见的,这似乎导致人们在其他答案中遇到各种困惑(例如/在文件路径中)
问题 4:现在我应该如何处理这一切?
以 pam.sshd 的几行为例
# PAM configuration for the Secure Shell service
# Standard Un*x authentication.
@include common-auth
# Disallow non-root logins when /etc/nologin exists.
account required pam_nologin.so
抱歉太长了 - 认为值得解释整个过程
答案1
自从sedinsert.sh包含source
我假设您使用 bash 的命令。
问题1-2)
Q1.
你是对的。
Q2。
实际上,可以有一个带有换行符的变量:
sedinsert="I am a
multi line variable
and I kind of work"
采购就可以了变量文件是一个有效的 bash 脚本。
出于您的目的,您可以使用此变量(在每个换行符前面附加反斜杠):
sedinsert="I am a \
multi line variable \
and I kind of work"
与 sed 一起使用时需要反斜杠。现在您可以使用您的命令而无需更改:
sed -i "\|$sedfind|a\ \n$sedinsert" $sedfile
问题2
sed 命令a \
应该与换行符一起使用,如下所示:
sed -i "\|$sedfind|a \
$sedinsert" $sedfile
例如,命令
sed "/ping/a \
pong" -i file.txt
pong
将在每个包含子字符串“ping”的字符串后面添加一个字符串(没有额外的换行符和空格)。
如果您不喜欢它的外观,可以使用$'word'
机制来表示换行符:
sed "/ping/a \"$'\n'"pong" -i file.txt
或者
newline=$'\n'
sed "/ping/a \${newline}pong" -i file.txt
问题3
首先,每个符号都图案(例如 的值sedfind
)不包含它。文件的内容$sedfile
并不重要。分隔符仅用于指示模式结束。其次,如果需要在模式中使用分隔符,可以使用反斜杠转义所有出现的字符:
sed "\|bar\|bar| a \
foo-foo"
将foo-foo
在每个包含的字符串后面添加一个字符串bar|bar
是否有一些建议/标准的模糊分隔符可供使用,但在其他地方很少使用?
我对此一无所知。
顺便说一句,我的 sed 版本不接受俄语字符作为分隔符(错误消息delimiter character is not a single-byte character
)。
概括
现在你可以使用这个变量文件:
sedfind="# Standard Un\*x authentication." # all occurrences of symbol '|' must be escaped by backslash as far as '|' is sed pattern delimiter
#sedfind=".* Standard Un\*x authentication"
sedinsert="I am a \
multi line variable \
and I kind of work"
sedfile=sshd
和这个sedinsert.sh:
set -x
source $1
sed -i "\|$sedfind|a \
$sedinsert" $sedfile
最好用双引号将变量引起来(否则脚本将在具有特殊符号的文件名上崩溃):
set -x
source "$1"
sed -i "\|$sedfind|a \
$sedinsert" "$sedfile"
该脚本将在与模式匹配的$sedinsert
每一行文件之后添加字符串。$sedfile
$sedfind
关于引用、正则表达式和 sed 脚本编写的好教程,人们可能会发现它很有用:http://www.grymoire.com/Unix/