Автор Тема: sed и спец символы в переменных bash  (Прочитано 1093 раз)

Оффлайн zah

  • Давно тут
  • **
  • Сообщений: 140
  • ^_^
   Всем привет!

Хочу задать вопрос на конкретном примере. Задача, заменить:

GRUB_CMDLINE_LINUX_DEFAULT='resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04 panic=30 quiet splash smem=1'

на

GRUB_CMDLINE_LINUX_DEFAULT='resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04 panic=30 smem=1'

Делаю это следующим образом:
GRUB2='/etc/sysconfig/grub2'
GRUB_STR=`grep GRUB_CMDLINE_LINUX_DEFAULT $GRUB2`

for (( i = 1; i < 6; i++ )); do
        CMDLINE=`grep GRUB_CMDLINE_LINUX_DEFAULT $GRUB2 | cut -d' ' -f$i`
        if [[ "$CMDLINE" != "quiet" && "$CMDLINE" != "splash" ]]; then
                GRUB_ARRAY[$i]=$CMDLINE
        fi
done

NEW_GRUB=`printf ${GRUB_ARRAY[*]}`

sed -i "s/$GRUB_STR/$NEW_GRUB/g" $GRUB2

Ошибка:
++ printf 'GRUB_CMDLINE_LINUX_DEFAULT='\''resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04' panic=30 'smem=1'\'''
+ NEW_GRUB='GRUB_CMDLINE_LINUX_DEFAULT='\''resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04'
+ sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT='\''resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04 panic=30 quiet splash smem=1'\''/GRUB_CMDLINE_LINUX_DEFAULT='\''resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04/g' /etc/sysconfig/grub2
sed: -e выражение #1, символ 43: неизвестный модификатор к `s'

Обычно заменяю спец символы на hex запись, но как быть когда это в переменных находится?

Оффлайн glebfm

  • alt linux team
  • ***
  • Сообщений: 35
Re: sed и спец символы в переменных bash
« Ответ #1 : 24.03.2021 20:59:20 »
Мне кажется, что если проще использовать только sed, например, вот так:

sed -E -e "s/(^GRUB_CMDLINE_LINUX_DEFAULT=[\"'](|.* ))quiet ?(.*)/\1\3/" -e "s/(^GRUB_CMDLINE_LINUX_DEFAULT=[\"'](|.* ))splash ?(.*)/\1\3/"

Но на самом деле у меня есть и ответ на поставленный вопрос -- в пакете libshell есть shell-quote, в котором есть функции quote_sed_regexp и quote_sed_regexp_variable, по поводу которых в shell-quote(3) есть такие примеры:
   quote_sed_regexp
       Function quotes given arguments for sed basic regular expression.  Usage example:
           sed "s/$(quote_sed_regexp "$var_pattern")/$(quote_sed_regexp "$var_replacement")/"

   quote_sed_regexp_variable
       Function quotes argument for sed basic regular expression and stores result into variable.  Usage example:
           quote_sed_regexp_variable var_pattern "$pattern"
           quote_sed_regexp_variable var_replace "$replace"
           sed "s/$var_pattern/$var_replace/"


По поводу приведённого кода на bash -- можно сделать вот так:
#!/bin/sh -efu

. shell-quote
 
GRUB_CFG=/etc/sysconfig/grub2
GRUB_STR="$(sed -E "s/^GRUB_CMDLINE_LINUX_DEFAULT=['\"](.*)['\"]$/\1/" "$GRUB_CFG")"

set -- $GRUB_STR

NEW_STR=
for i; do
        case "$i" in
                quiet|splash) continue ;;
        esac
        NEW_STR="${NEW_STR:+$NEW_STR }$i"
done

sed "s/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT='$(quote_sed_regexp "$NEW_STR")'/" -i "$GRUB_CFG"
« Последнее редактирование: 24.03.2021 22:26:56 от glebfm »

Оффлайн Koi

  • alt linux team
  • ***
  • Сообщений: 1 893
  • валар дохаэрис
    • Канал на youtube
Re: sed и спец символы в переменных bash
« Ответ #2 : 25.03.2021 02:04:56 »
   Всем привет!

Хочу задать вопрос на конкретном примере. Задача, заменить:

GRUB_CMDLINE_LINUX_DEFAULT='resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04 panic=30 quiet splash smem=1'

на

GRUB_CMDLINE_LINUX_DEFAULT='resume=/dev/disk/by-uuid/7506ccaa-b82d-4220-8388-3038782aee04 panic=30 smem=1'
Удалить quiet splash?
line="GRUB_CMDLINE_LINUX_DEFAULT="
sed -i "/$line/s/quiet//;/$line/s/splash//;/$line/s/  //" $file
« Последнее редактирование: 25.03.2021 09:24:39 от Koi »