【问题标题】:sed replace using shell variablessed 使用 shell 变量替换
【发布时间】:2016-10-06 03:19:47
【问题描述】:

我在 Linux Mint 17 上

我得到了这个命令来查看这里的其他 sed 问题,但似乎无法让它工作。谁能建议这里有什么问题?这看起来很简单,但行不通:

$ cat t | sed "s/${FSTAB_UUID}/${SWAP_UUID}/"

sed:-e 表达式 #1,字符 2:未终止的 `s' 命令

$ echo $FSTAB_UUID

15542fac-468c-405f-a156-dd781ece7568

$ echo $SWAP_UUID

2891fb61-26c3-4606-b310-6c12e4788db5

$ cat t

UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=15542fac-468c-405f-a156-dd781ece7568 none  swap  rw 0 0

【问题讨论】:

  • 使用busybox sed按预期工作。
  • 好的,我在 Linux Mint 17 上
  • 在 GNU sed 4.2.2 中也可以正常工作。你用的是什么外壳?
  • 请添加echo ">>$SWAP_UUID<<"echo ">>$FSTAB_UUID<<" 的输出以查看变量中是否有尾随换行符或其他内容
  • 与您的问题无关,但cat 是不必要的。 sed 是一个过滤器程序,它以文件名作为其最右边的参数。

标签: bash shell sed


【解决方案1】:

使用您的代码,我在 Linux(bash 4.3.11 GNU sed 4.2.2)上遇到类似(仅)错误:

$ FSTAB_UUID=15542fac-468c-405f-a156-dd781ece7568
$ SWAP_UUID=2891fb61-26c3-4606-b310-6c12e4788db5
$ cat t |  sed "s/${FSTAB_UUID}/${SWAP_UUID}/"
sed: -e expression n°1, caractère 0: pas d'expression régulière précédente

(翻译:sed:-e 表达式#1,字符 0:没有前面的正则表达式)

但不是在 FreeBSD (10.2-RELEASE) 上。我不知道为什么,也找不到任何关于 GNU sed 和经典 sed 之间差异的解释。

现在,在我的 Linux 机器上,虽然这可能不是最漂亮的解决方法,而且尽管行为不应该与您的代码不同,但这还没有达到预期的效果结果:

$ cat t |  sed 's/'"${FSTAB_UUID}"'/'"${SWAP_UUID}"'/'
UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=2891fb61-26c3-4606-b310-6c12e4788db5 none  swap  rw 0 0
$ cat t
UUID=accbd859-7cdd-4d00-86ea-2b5d7d1cee75 /     ext4  errors=remount-ro 0 1
UUID=15542fac-468c-405f-a156-dd781ece7568 none  swap  rw 0 0
$ 

(只需将sed 部分放在单引号中,并将变量放在双引号之间)。

【讨论】:

  • 从我的角度来看应该对 OP 的代码没有任何影响
  • @StefanHegny 我的代码确实有错误(见编辑#2)
  • 这与版本问题有关吗?我的是GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
  • sed (GNU sed) 4.2.2
  • 错误出现在 Mint 17 BASH 4.3.11 和 cygwin BASH 4.3.32 上
【解决方案2】:

我可以通过确保$FSTAB_UUID 的值以换行符开头(如@StefanHegny 所建议)来重现您的问题:

$ FSTAB_UUID="
> 15542fac-468c-405f-a156-dd781ece7568"
$ echo $FSTAB_UUID
15542fac-468c-405f-a156-dd781ece7568
$ echo ">>>$FSTAB_UUID<<<"
>>>
15542fac-468c-405f-a156-dd781ece7568<<<
$ sed "s/${FSTAB_UUID}/${SWAP_UUID}/" t
sed: -e expression #1, char 2: unterminated `s' command

(请注意,第二行前导的&gt;bash 发出的辅助提示;它不是输入的一部分。)我看不到该行为的其他解释。

最好的解决方案是设置$FSTAB_UUID$SWAP_UUID 的值,不要引入前导或尾随换行符。我无法更具体,因为不清楚他们最初是如何进入的。

如果您无法将换行符排除在外,那么您也可以选择在事后将其删除。这有点难看,但它会从两个值中删除所有前导和尾随空格,包括换行符:

FSTAB_UUID=${FSTAB_UUID##+([[:space:]])}
FSTAB_UUID=${FSTAB_UUID%%+([[:space:]])}
SWAP_UUID=${SWAP_UUID##+([[:space:]])}
SWAP_UUID=${SWAP_UUID%%+([[:space:]])}

参数扩展中的##%% 告诉bash 分别修剪与以下模式匹配的最长前缀或后缀。就其本身而言,该模式匹配任意正数空白字符的字符串。

【讨论】:

  • 这是正确的,我使用另一个 awk 正则表达式先去除换行符,它工作正常。
猜你喜欢
  • 2014-01-09
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 2021-11-20
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多