在 Linux 上使用 sed 命令时遇到问题

在 Linux 上使用 sed 命令时遇到问题

sed我在替换文件中的内容时遇到一些奇怪的命令问题。我创建了一个只有几行的虚拟文件并尝试执行我的脚本。有效。

当我使用该文件时,相同的脚本无法替换字符串lvm.conf

任务是将磁盘路径附加到文件global_filterlvm.conf

输入将是/dev/sdb1,我必须将相同的内容添加到global_filter global_filter = ["a|^/dev/sda2$|", "r/.*/"]

我的脚本如下:

#!/bin/sh

function addToFilter(){
    app_lvm_conf="/etc/lvm/lvm.conf"
    line=$(sed -n '/global_filter =/p' $app_lvm_conf)
    echo $line
    exstngfltr=$(echo $line | cut -d "[" -f2 | cut -d "]" -f1)
    echo $exstngfltr
    IFS=', ' read -r -a array <<< "$exstngfltr"
    echo ${array[@]}
    numOfEntries=${#array[@]}
    echo $numOfEntries
    value=$(IFS=,; echo "${array[*]}")
    echo $value
    temp="${array[numOfEntries-1]}"
    echo $temp

    ar=$1
    echo $ar
    a='"a|^'
    b='$|"'
    z=$a$1$b
    echo $z
    array[numOfEntries-1]=$z
    array[numOfEntries]=$temp
    newValue=$(IFS=,; echo "${array[*]}")
    sed -i "s@$value@$newValue@g" $app_lvm_conf
}
addToFilter $1

我使用了多个 echo 语句来查看输出,一旦脚本正常工作,我将删除它们。


输入是"/dev/sda2"

文件中的预期输出lvm.conf是:

global_filter = ["a|^/dev/sda1$|","a|^/dev/sda2$|","r/.*/"]

文件中将有一个global_filter条目。lvm.conf执行此脚本时,该过滤器应该得到更新。

由于该文件很大,我已将global_filter存在的部分复制粘贴到单独的文件中并进行相同的处理。

lvm.conf 文件

# Since "filter" is often overridden from command line, it is not suitable
# for system-wide device filtering (udev rules, lvmetad). To hide devices
# from LVM-specific udev processing and/or from lvmetad, you need to set
# global_filter. The syntax is the same as for normal "filter"
# above. Devices that fail the global_filter are not even opened by LVM.

global_filter = ["a|^/dev/dasda2$|", "r/.*/"]

# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.

执行脚本时,文件应更改如下

# Since "filter" is often overridden from command line, it is not suitable
# for system-wide device filtering (udev rules, lvmetad). To hide devices
# from LVM-specific udev processing and/or from lvmetad, you need to set
# global_filter. The syntax is the same as for normal "filter"
# above. Devices that fail the global_filter are not even opened by LVM.

global_filter = ["a|^/dev/sda1$|", "a|^/dev/sda2$|", "r/.*/"]

# The results of the filtering are cached on disk to avoid
# rescanning dud devices (which can take a very long time).
# By default this cache is stored in the /etc/lvm/cache directory
# in a file called '.cache'.

脚本的输入应严格属于 类型/dev/sda2

答案1

我相信这可以满足您的需要:

addition=', "a|^/dev/sda2$|"'
expression='/global_filter/ s@(, "r)@'"$addition"\\1'@'
sed -r -i.orig "${expression}" /etc/lvm.conf

这里的技巧是使用 sed 的模式匹配来匹配 /global_filter/ 的行,然后使用搜索/替换,仅替换逗号周围的位: , "r

与您的新添加。

sed 此处需要 '-r' 标志,以便捕获带有括号 '(pattern)' 的 ' , "r ' 部分,以便您可以在添加后使用反向引用 "\1" 重新插入它

或者,更容易理解,没有 -r 和 '()' 匹配:

addToFilter()
{
  device="${1}"
  addition='"a|^'"${device}"'$|"'

  insert_before=', "r'

  replacement=", ${addition}${insert_before}"

  line_match="global_filter"

  expression="/${line_match}/ s@${insert_before}@${replacement}@"

  sed -i.orig -e "${expression}" /etc/lvm.conf
} 

addToFilter "/dev/sda2"

我假设示例输入文件中的“dev/dasda2”不是真正的输入,而是因编辑失败而留在那里。

相关内容