使用父脚本中定义的函数

使用父脚本中定义的函数

我在test.sh中编写了以下脚本:

#!/bin/sh
compare() { 
if [ $1 != root ]; then 
echo "Fail" >> CAT1.txt 
fi 
}
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c 'compare "$@"' _

当我执行此脚本时,出现以下错误:

_: compare: command not found

答案1

函数是定义它的 shell 的内部函数。如果您运行另一个程序,该另一个程序将看不到该函数,即使它恰好也是一个 shell。

(可以在子 shell 中访问函数,即当制作正在运行的 shell 的副本来运行括号中的某些内容(…)或用于命令替换$(…)等时。但它们不能在单独的程序中访问,例如当您运行时sh -c …。)

在使用该函数的脚本中定义该函数:

#!/bin/sh
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c '
  compare() { 
  if [ $1 != root ]; then 
  echo "Fail" >> CAT1.txt 
  fi 
  }
  compare "$@"' _

(我假设这是一个玩具示例,这一切都可以在一个简单的 awk 脚本中完成。)

或者,您可以使用 bash 功能,该功能允许通过环境将函数导出到 bash 的子实例。这是 bash 特定的功能,因此父脚本必须运行 bash,而不是 sh。

#!/bin/bash
compare() { 
if [ $1 != root ]; then 
echo "Fail" >> CAT1.txt 
fi 
}
export -f compare
awk -F: '$4 == 0' /etc/passwd | cut -d: f1 | xargs -n1 -i bash -c 'compare "$@"' _

答案2

  1. 为什么不使用...?

    awk -F: '$4==0 && $1 != root ' /etc/passwd > CAT1.txt
    

    1.1 编辑得到Fail

    awk -F: '$4==0 && $1 != root {print "Fail" ; } /etc/passwd > CAT1.txt
    

    获取失败和用户名

    awk -F: '$4==0 && $1 != root {printf "Fail %s\n",$1 ; } /etc/passwd > CAT1.txt
    
  2. 分叉新的 bash 时,函数定义会丢失。 Ae @mueh 告诉你,你需要export -f compare

答案3

您应该使用某种分叉逻辑来执行此操作。在脚本的环境中设置一些标记,这肯定会向脚本的子实例证明它们应该做一件事,而父级则做另一件事。通过这种方式,您可以使脚本安全地递归。

#!/bin/sh
case $Z:$P in 
("$0:${1:-!$P}")
     [ root = "$2" ] ||
     ! echo Fail
;;(*)
     set -a; Z=$0 P=$$
     </etc/passwd     \
     awk -F: '$4 == 0'|
     cut -d: -f1      |
     xargs -n1 "$0" "$$"
esac >>CAT1.txt

或者,也许使用您的 fds 来进行检查。如果您首先从终端运行脚本,那么......

#!/bin/sh
[ -t 0 ] && {
     awk '$4 == 0' |
     cut   -d: -f1 |
     xargs -n1 "$0"
     exit
} </etc/passwd >>CAT1.txt
[ root = "$1" ]   ||
! echo Fail

但最好的方法实际上是改变孩子的$0

#!/bin/sh
[ . = "$0" ] && {
    [ root = "$1" ] ||
    ! echo Fail
}
z=$(head -n5 <"$0")
</etc/passwd  \
awk '$4 == 0' |
cut -d:  -f1  |
>>CAT1.txt    \
xargs -n1     \ 
sh -c "$z" . 

相关内容