我有一个包含很多行的文件,其中两行是:
videoId: 'S2Rgr6yuuXQ'
var vid_seq=1;
在shell脚本中,我有两个变量, 对于id,值始终为11个字符/数字
ID = 'fsafsferii2'
id_seq = 80
我想用id和id_seq修改这两行
videoId: 'fsafsferii2'
var vid_seq=80;
我用过
sed -i 's/\(videoId: \).*\\1'${id}'/\2' file
但是有错误,我的脚本出了什么问题?
感谢
答案 0 :(得分:3)
grep
命令不会“替换”文本,而是“全局正则表达式打印”。但是sed会。
sed -i'' '/^videoId: /s/: .*/: '"$id"'/;/^var vid_seq=/s/=.*/='"$id_seq"';/'
我不喜欢以这种方式将变量插入到sed脚本中,但是sed很简单,并没有提供实际使用实际变量的机制。如果您要这样做,请在运行此sed脚本之前,对两个变量进行一些格式检查,以确保它们包含您希望它们包含的数据。变量中的意外/
会导致sed脚本失败。
更新:
这是一个成功的测试:
$ id=fsafsferii2
$ id_seq=80
$ cat inp686
videoId: 'S2Rgr6yuuXQ'
var vid_seq=1;
$ sed '/^videoId: /s/: .*/: '"$id"'/;/^var vid_seq=/s/=.*/='"$id_seq"';/' < inp686
videoId: fsafsferii2
var vid_seq=80;
$
当然,你需要做一些引用魔术来将单引号引入你的videoId,但我相信你可以自己解决这个问题。
更新2
根据sed的手册页,substitute命令的格式为:
[2addr]s/regular expression/replacement/flags
[2addr]
表示您最多可以指定两个“地址”,可以是行号或正则表达式来匹配。因此s
(替换)命令可以在匹配之间采用行,范围,匹配或跨度。在我们的例子中,我们只是使用一个匹配来确定我们想要执行替换的行。
上面的脚本由两个sed命令组成,用分号分隔。
/^videoId: /
- 匹配以videoId:
开头的行...
s/: .*/: '"$id"'/;
- 使用$id
环境变量中的任何内容将冒号中的所有文本替换为行尾。/^var vid_seq=/
- 匹配...... meh,如上所述。
s/=.*/='"$id_seq"';/
- 使用$id_seq
替换等号中的所有文字。请注意,'"$id"'
构造意味着我们退出单引号,然后立即输入双引号以扩展变量...然后退出双引号并返回一组新的单引号。 Sed脚本在单引号内最安全,因为频繁使用可能由shell解释的字符。
另请注意,因为sed的substitute命令使用正斜杠作为分隔符,所以$id
和$id_seq
变量可能不包含斜杠。如果可能,您可以切换到不同的分隔符。
答案 1 :(得分:1)
有什么问题:
sed -i 's/\(videoId: \).*\\1'${id}'/\2' file
/
)。有效语法为s/regex/replace/
不正确的正则表达式模式(我们假设${id}
已被替换)
\(videoId: \).*\\1fsafsferii2
告诉它匹配一个如下所示的字符串:
videoId: anything\1fsafsferii2
(正则表达式中的\\
与文字反斜杠匹配,因此\\1
将匹配文字反斜杠,后跟1
而非第一个子表达式
将匹配的字符串替换为\2
但由于只有一组括号,\2
实际上是空的。
此外,由于2.中的正则表达式模式与任何内容都不匹配,因此不会替换任何内容。
这应该有效(GNU sed)
sed -i 's/\(videoId: \).*/\1 \x27'${id}'\x27/
s/\(var vid_seq=\).*/\1'${id_seq}'\;/' file
注意:
\x27
是单引号的十六进制表示(以防止与其他单引号冲突)\;
以字面分号表示。如果;
未转义,则会将其解释为终止s
中的sed
命令。