在Bash中格式化标准输入(stdin)

34

我有一个来自另一个程序的多行字符串,想将其转换为SQL命令。我希望printf可以帮助我,但它似乎不起作用:

echo -e '1\n2\n3'|printf 'SELECT %s INTO MyTable'

我希望看到:

SELECT '1
2
3' INTO MyTable

但我得到了:

SELECT  INTO MyTable

如何让%s读取标准输入?

3个回答

53

使用 xargsstdin 转换为程序参数:

echo -n  -e '1\n2\n3' |xargs -0  printf 'SELECT %s INTO MyTable'

我知道有一种方法。我也在看xargs,但是无法完全拼凑起来。这正是我想要的。 - User1
1
这个方案很好,但是bash的printf和/usr/bin/printf可执行文件不同,这意味着你不能使用"%q"。我选择了@Dennis Williamson的功能命令。 - isaaclw
我遇到了一个“值未完全转换”的错误,通过使用“xargs -i printf'%s' {}”解决了这个问题。 - Asclepius

9

试一试这个:

printf_stdin() { local stdin; read -d '' -u 0 stdin; printf "$@" "$stdin"; }

echo -e '1\n2\n3' | printf_stdin 'SELECT %s INTO MyTable'

我认为应该使用printf_stdin() { local stdin; IFS='' read -r -d '' -u 0 stdin; printf "$1" "$stdin"; }。特别是IFS=''(没有它,我会丢失尾随的换行符)和-r(将输入中的\视为字面量)。"$1""$@"更有意义,后者可能会产生模棱两可的结果。 - undefined

2
你不能这样做。 printf shell命令格式化它的参数而不是标准输入,因此你可以做的是提供一个命令的输出作为单个参数:
bash$ printf "SELECT '%s' INTO MyTable" "`echo -e '1\n2\n3'`"
SELECT '1
2
3' INTO MyTable
bash$

编辑:使用Awk的解决方案

bash$ echo -e '1\n2\n3' | awk -v 'ORS=' '
   BEGIN { print "SELECT \"" }
   { print $0, "\n" }
   END { print "\" INTO MyTable" }'
SELECT "1
2
3
" INTO MyTable
bash$

我将把去除最后一个换行符的工作留给读者练习。如果你想在printf中做更复杂的操作,则需要想出一些更有创意的awk脚本。


有没有其他命令可以按照问题提出的顺序运行? - User1
你可能可以使用awk接近于你示例中简单的printf用法。我会在我的答案中添加它。 - D.Shawley
@User1,xargs 命令中有一些先例。它从 stdin 中获取数据,并将数据分成多个参数传递给“模板”命令。您可以编写一个小的 shell 程序(例如称为 1args),如 s="$(cat)";"$@" "$s",并将其用作 printf '%s\n' 1 2 3 | 1args printf "SELECT '%s' INTO MyTable\n" 来维护您的顺序。但我还不太确定它的实用性。参数的大小有限制(每个操作系统不同),这将限制您可以将多少 stdin 填充到一个参数中。 - Chris Johnsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接