Shell 使用sed或grep替换行中的子字符串

Shell 使用sed或grep替换行中的子字符串,shell,sed,grep,Shell,Sed,Grep,我有一个文件有很多行,其中两行是: 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 但是有错误,我的脚本怎么了 谢谢grep

我有一个文件有很多行,其中两行是:

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
但是有错误,我的脚本怎么了


谢谢grep命令不会“替换”文本,它用于“全局正则表达式打印”。但塞德会的

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;

$ 
[2addr]
意味着您最多可以指定两个“地址”,它们可以是行号或正则表达式来匹配。因此,
s
(substitute)命令可以获取一行、一个范围、一个匹配或匹配之间的跨度。在我们的例子中,我们只是使用一个匹配来确定要在哪些行上执行替换

上面的脚本由两个sed命令组成,用分号分隔

  • /^videoId:///code>--匹配以单词
    videoId:
    开头的行。。。
    • s/:*/:“$id”/
      --用
      $id
      环境变量中的任何内容替换从冒号到行尾的所有文本
  • /^var vid_seq=/
    ——匹配以下行:。。。嗯,如上所述。
    • s/=.*/='$id_seq'/
      --用
      $id\u seq
      替换equals登录中的所有文本
请注意,
“$id”
构造意味着我们将退出单引号,然后立即输入双引号以展开变量。。。然后退出双引号并返回一组新的单引号。Sed脚本在单引号中是最安全的,因为频繁使用可能由shell解释的字符


还请注意,由于sed的替换命令使用正斜杠作为分隔符,
$id
$id_seq
变量可能不包含斜杠。如果可能,您可以切换到其他分隔符。

grep
命令不会“替换”文本,而是用于“全局正则表达式打印”。但塞德会的

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;

$ 
[2addr]
意味着您最多可以指定两个“地址”,它们可以是行号或正则表达式来匹配。因此,
s
(substitute)命令可以获取一行、一个范围、一个匹配或匹配之间的跨度。在我们的例子中,我们只是使用一个匹配来确定要在哪些行上执行替换

上面的脚本由两个sed命令组成,用分号分隔

  • /^videoId:///code>--匹配以单词
    videoId:
    开头的行。。。
    • s/:*/:“$id”/
      --用
      $id
      环境变量中的任何内容替换从冒号到行尾的所有文本
  • /^var vid_seq=/
    ——匹配以下行:。。。嗯,如上所述。
    • s/=.*/='$id_seq'/--将等号上的所有文本替换为
      $id\u seq
请注意,
“$id”
构造意味着我们将退出单引号,然后立即输入双引号以展开变量。。。然后退出双引号并返回一组新的单引号。Sed脚本在单引号中是最安全的,因为频繁使用可能由shell解释的字符

还请注意,由于sed的替换命令使用正斜杠作为分隔符,
$id
$id_seq
变量可能不包含斜杠。如果可能,您可以切换到其他分隔符。

有什么问题:

sed -i 's/\(videoId: \).*\\1'${id}'/\2' file
  • 缺少第三个分隔符(
    /
    )。有效语法为
    s/regex/replace/
  • 不正确的正则表达式模式(假设已替换了
    ${id}

    告诉它匹配如下所示的字符串:

    videoId: anything\1fsafsferii2
    
    \\
    在正则表达式中匹配文字反斜杠,因此
    \\1
    将匹配文字反斜杠,后跟
    1
    ,而不是第一个子表达式)

  • 将匹配的字符串替换为
    \2

    但由于只有一组括号,
    \2
    实际上是空的

    另外,由于2中的正则表达式模式。任何东西都不匹配,没有任何东西被替换


  • 这应该有效(GNU-sed)

    注:

    • \x27
      是单引号的十六进制表示形式(以防止与其他单引号冲突)
    • \表示文字分号。如果
      不是转义的,它被解释为终止
      sed
      中的
      s
      命令
    有什么问题:

    sed -i 's/\(videoId: \).*\\1'${id}'/\2' file
    
  • 缺少第三个分隔符(
    /
    )。有效语法为
    s/regex/replace/
  • 不正确的正则表达式模式(假设已替换了
    ${id}

    告诉它匹配一个字符串