AWK逃脱角色混乱

时间:2016-02-23 03:36:14

标签: bash awk

所以我一直在读AWK,但我似乎在执行以下代码时出现问题:

curl http://website.com/users.csv | tac | tac | sed '101,400!d' | grep "female" |
awk -F',' '{ print "sudo useradd -Db /home/gender/female" " " $1 " " "-c" " " \"$5 " " $6\""}' |
bash

我试图在$5之前和$6之后立即转义双引号,这样我就可以从AWK进行系统调用,或者只是管道进行bash。由于某种原因,我的转义字符不起作用。我读了关于转义序列的这个GNU AWK摘要无济于事。

我怎样才能做到这一点?

输出应如下所示:

sudo useradd -Db /home/gender/female dinessid1965 -c "Marina Propst"

输入如下:

reatim,Shephoi8v,female,Ms.,Eija,Kankkunen,4721 Pearcy Avenue,Fort Wayne,IN,46804,,260-715-7242,2/22/84,Pisces,Dermatologist

3 个答案:

答案 0 :(得分:2)

首先,对于逃避:你通过单独引用所有内容来使你的生活更加艰难。而不是

print "sudo useradd -Db /home/gender/female" " " $1 " " "-c" " " \"$5 " " $6\""
你可以写

print "sudo useradd -Db /home/gender/female " $1 " -c " \"$5 " " $6\""

此时引用的内容变得更加明显:GNU Awk抱怨\不是该行的最后一个字符。

您可以这样写,引号之间的转义引用\"

print "sudo useradd -Db /home/gender/female " $1 " -c \"" $5 " " $6 "\""

或更容易阅读,指定包含双引号的变量(请参阅manual):

awk -v dq='"' '{ print "sudo useradd -Db /home/gender/female " $1 " -c " dq $5 " " $6 dq }'

其次,你的整个链可以简化:tac | tac什么都不做,grep和sed可以用awk做什么:

curl http://website.com/users.csv |
awk -F, -v dq='"' '/female/ && NR >= 101 && NR <= 400 { \
 print "sudo useradd -Db /home/gender/female " dq $1 dq " -c " dq $5 " " $6 dq }' |
bash

或者,为了避免使用print在变量之间添加空格的一些丑陋,我们可以使用printf(感谢Ed Morton轻推):

curl http://website.com/users.csv |
awk -F, '/female/ && NR >= 101 && NR <= 400 { \
printf "sudo useradd -Db /home/gender/female \"%s\" -c \"%s %s\"\n", $1, $5, $6 }' |
bash

注意最后两个命令中引用$1的扩展是如何防止shell特有的字符(甚至是恶意命令)的副作用。

答案 1 :(得分:1)

你完全涉及到awk,这使得这比必要的更难。它也很危险,因为您没有为shell引用$1$5$6的内容。如果它们包含任何有趣的角色,那你就麻烦了。

你可以完全用bash安全地完成它:

curl http://website.com/users.csv | sed '101,400!d' | grep "female" |
while IFS=, read -a words; do
    sudo useradd -Db /home/gender/female "${words[0]}" -c "${words[4]} ${words[5]}"
done

虽然为了更加安全,您可能需要确保用户名字段不包含任何可疑内容(例如,以../开头)。我不知道检查useradd有多少。

答案 2 :(得分:0)

你正在使用太多的报价!

以下是一个可以更改为格式的简单示例

$ echo dinessid1965,two,three,four,Marina,Propst |
   awk -F, -v q='"' '{print "sudo ...", $1, "-c", q $5, $6 q}'  

sudo ... dinessid1965 -c "Marina Propst"