printf "ест" обратную косую черту.Как их сохранить? - PullRequest
1 голос
/ 14 июня 2019

Я пытаюсь создать крошечную POSIX-совместимую sed-подобную функцию. Однако я заметил, что код ниже "съедает" обратную косую черту.

input.txt для mysed ./input.txt "TEST2" "TEST2=\"two\"" звоните:

TEST1="\\_PR.CP%02d"
TEST2="one"
TEST3="\\_PR.P%03d"

Ожидаемый:

TEST1="\\_PR.CP%02d"
TEST2="two"
TEST3="\\_PR.P%03d"

Поступило:

TEST1="\_PR.CP%02d"
TEST2="two"
TEST3="\_PR.P%03d"

Как изменить приведенный ниже код, чтобы сохранить все обратные слеши? Может быть, можно заменить пользовательский формат printf '%b\n' на что-то лучшее?

#!/bin/sh
# Replaces the lines containing the text '$2' of a file '$1' with a line '$3'.
mysed () {
    if [ -f "$1" ] ; then
        mysed_tmp="./.mysed"
        rm -f $mysed_tmp
        while IFS= read -r line
        do
            case $line in
                *"$2"*)
                    if [ ! -z "$3" ] ; then
                        printf '%b\n' "$3" >> $mysed_tmp
                    fi
                    ;;
                *)
                    printf '%b\n' "$line" >> $mysed_tmp
                    ;;
            esac
        done < "$1"
        mv $mysed_tmp $1
        return 0
    else
        return 1
    fi
}

echo "TEST1=\"\\\\_PR.CP%02d\"" > input.txt
echo "TEST2=\"one\"" >> input.txt
echo "TEST3=\"\\\\_PR.P%03d\"" >> input.txt

mysed ./input.txt "TEST2" "TEST2=\"two\""
cat ./input.txt

РЕДАКТИРОВАНИЕ: заменено '%b\n' на '%s\n', теперь все работает как положено.

1 Ответ

2 голосов
/ 14 июня 2019

Посмотрите:

$ x="TEST2=\"two\""; printf '%s\n' "$x"
TEST2="two"

$ x='TEST2=\"two\"'; printf '%s\n' "$x"
TEST2=\"two\"

$ TEST1="\\_PR.CP%02d"; printf '%s\n' "$TEST1"
\_PR.CP%02d

$ TEST1='\\_PR.CP%02d'; printf '%s\n' "$TEST1"
\\_PR.CP%02d

Надеюсь, это прояснит ситуацию:

$ foo() { printf '%%b:<%b>\n%%s:<%s>\n---\n' "$1" "$1"; }

$ foo "TEST2=\\"two\\""
%b:<TEST2=      wo\>
%s:<TEST2=\two\>
---

$ foo 'TEST2=\\"two\\"'
%b:<TEST2=\"two\">
%s:<TEST2=\\"two\\">
---

Итак:

  1. Если вы не хотите, чтобы обратная косая черта удалялась оболочкой, когда строка определена, не говорите оболочке, чтобы она их интерпретировала - используйте ', а не ".
  2. Если вы не хотите, чтобы обратная косая черта удалялась printf при печати строки, не говорите printf, что нужно их интерпретировать - используйте %s, а не %b.
...