shell 脚本内的输入变量和管道变量发生冲突

shell 脚本内的输入变量和管道变量发生冲突

我有以下脚本:

#!/bin/bash
cat $1.txt | awk "{cmd=\"pwgen 10 1\"; cmd | getline pass; print substr($0, 1, length($0) -1) \">> ~/dresses/whole-dresses-shape/$1-\" pass \".jpg\"; close(cmd);}" | bash

在命令内部awk "{}"$0变量应该引用当前正在读取的行cat $1.txt。但是,当从脚本文件内部使用时,$0将采用正在执行的文件名称的值。

如何确保该函数获取本示例中substr()的输出?cat

所需的工作流程:

  • 用户输入./myscript.sh hello
  • $1有价值hello
  • 读取的每一行都cat分配给当前显示的内容 $0

答案1

这里有几种方法可以更干净地完成它(使用printfin 代替print+ 字符串连接是个人喜好的问题 - 我发现在这种情况下它更具可读性)。

  1. $1导出awk数组 ex的值并使用它ENVIRON

    #!/bin/bash
    
    export var="$1"
    
    cat "$1.txt" | awk '
      BEGIN{cmd="pwgen 10 1"} 
      {
        cmd | getline pass; 
        printf "%s >> ~/dresses/whole-dresses-shape/%s-%s.jpg\n", substr($0, 1, length($0) -1), ENVIRON["var"], pass;
        close(cmd);
      }
    '
    
  2. 使用命令行-v选项传递$1ex 的值。

    #!/bin/bash
    
    cat "$1.txt" | awk -v var="$1" '
      BEGIN{cmd="pwgen 10 1"} 
      {
        cmd | getline pass; 
        printf "%s >> ~/dresses/whole-dresses-shape/%s-%s.jpg\n", substr($0, 1, length($0) -1), var, pass;
        close(cmd);
      }
    '
    

这两者都用“硬”引号替换外部“软”引号。一个附带的好处是,它可以释放一层引用,以防您希望保护输出来自分词的字符串(可能是好的做法 - 因为您显然将结果通过管道传输到 shell),例如。

printf "\"%s\" >> ~\"/dresses/whole-dresses-shape/%s-%s.jpg\"\n"

-v有关与的讨论,ENVIRON请参阅

答案2

像这样做:

variable="but put shell variable in double quotes"

echo 'Put most of the awk script in single quotes so that $s are not expanded, '"$variable"', then continue in single quotes.'

但是,请阅读 @Paul_Pedant 关于将代码注入程序的评论。

答案3

我会在 awk 中使用单引号。未测试

#!/bin/bash
cat $1.txt | awk '{cmd="pwgen 10 1"; cmd | getline pass; print substr($0, 1, length($0) -1) ">> ~/dresses/whole-dresses-shape/'$1'-" pass ".jpg"; close(cmd);}' | bash

相关内容