printf 是 "eating" 的反斜杠。如何保存它们?

printf is "eating" the backslashes. How to preserve them?

我正在尝试制作一个小巧的 POSIX 兼容的类似 sed 的函数。但是我注意到下面的代码是 "eating" 反斜杠。

input.txtmysed ./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 '' of a file '' with a line ''.
mysed () {
    if [ -f "" ] ; then
        mysed_tmp="./.mysed"
        rm -f $mysed_tmp
        while IFS= read -r line
        do
            case $line in
                *""*)
                    if [ ! -z "" ] ; then
                        printf '%b\n' "" >> $mysed_tmp
                    fi
                    ;;
                *)
                    printf '%b\n' "$line" >> $mysed_tmp
                    ;;
            esac
        done < ""
        mv $mysed_tmp 
        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',现在一切正常。

看:

$ 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' "" ""; }

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

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

所以:

  1. 如果您不想在定义字符串时被 shell 去除反斜杠,那么不要让 shell 解释它们 - 使用 ' 而不是 ".
  2. 如果您不希望在打印字符串时 printf 去除反斜杠,则不要告诉 printf 解释它们 - 使用 %s 而不是 %b.