Linux에서 sed 명령을 사용하는 데 문제가 있습니다.

Linux에서 sed 명령을 사용하는 데 문제가 있습니다.

sed파일의 내용을 바꾸는 데 이상한 명령 문제가 있습니다. 몇 줄만으로 더미 파일을 만들고 스크립트를 실행해 보았습니다. 효율적인.

파일을 사용할 때 동일한 스크립트가 문자열을 바꾸지 못합니다 lvm.conf.

global_filter작업은 파일 에 디스크 경로를 추가하는 것입니다 lvm.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는 역참조 "\1"을 사용하여 추가한 후 다시 삽입할 수 있도록 '(패턴)' 대괄호가 있는 ' , "r ' 부분을 캡처하기 위해 여기에 '-r' 플래그가 필요합니다.

또는 -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"는 실제 입력이 아니지만 편집 실패로 인해 남아 있다고 가정합니다.

관련 정보