printf正在“吃”反斜杠。如何保存它们?

时间:2019-06-14 12:24:57

标签: bash shell printf sh posix

我正在尝试制作一个与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 个答案:

答案 0 :(得分:2)

看:

$ 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