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
関数は、その関数が定義されているシェルの内側にあります。別のプログラムを実行すると、そのプログラムがシェルであってもその機能を見ることはできません。
(関数はサブシェルからアクセスできます。つまり、実行中のシェルのコピーを作成して角かっこ内のエントリを実行したり、コマンドの置き換えなど(…)
の$(…)
ためにアクセスしたりできます。ただし、別のプログラムではアクセスできません(例:とき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固有の機能なので、親スクリプトはshではなくbashを実行する必要があります。
#!/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
なぜ使用しないのですか…?
awk -F: '$4==0 && $1 != root ' /etc/passwd > CAT1.txt
1.1 編集に失敗する
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
新しいbashをフォークすると、関数定義が失われます。 Ae @ muehあなたに必要だと言います
export -f compare
。
答え3
これを行うには、ある種の分岐ロジックを使用する必要があります。スクリプトの子インスタンスが1つのタスクを実行し、親インスタンスが別のタスクを実行する必要があることを確実に示すフラグをスクリプト環境に設定します。これにより、スクリプトを安全に再帰的に作成できます。
#!/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" .