Bash、標準入力ファイル名?

Bash、標準入力ファイル名?

標準入力からの「<」や「>」などの記号を計算するには、bashスクリプトを作成する必要があります。

たとえば、

$ ./myscript.sh <example.html
> - 20
< - 21
Found mismatching brackets!

私はこれをしました:

x=`grep -o '>' example.html | wc -l`
y=`grep -o '<' example.html | wc -l`
if [ "$x" -ne "$y" ]; then
  echo "Mismatch!"
fi
echo $x
echo $y

これは良いアプローチですか?標準入力から「example.html」ファイル名を取得する方法がわかりません。

ベストアンサー1

ポイントはstdin何でもできるということです。たとえば、パイプ、ネットワークソケット、汎用ファイル、デバイスなど、スクリプトが起動すると通常ファイルの半分になる可能性があります。閲覧可能ファイル、つまり通常のファイルと一部のデバイスファイルまたは情報は、何らかの方法で保存する必要があります(一時ファイルまたはメモリ...)。ただし、すべての情報はここですぐに確認できます。

たとえば、次のようにできます。

$ grep -o '[<>]' < a.html | sort | uniq -c
     82 <
     82 >

POSIX的に:

fold -w 1 a.html | grep '[<>]' | sort | uniq -c

不一致を検出するには:

if fold -w 1 a.html | awk '{n[$0]++}
     END{exit(n["<"]!=n[">"])}'
then
  echo match
else
  echo mismatch
fi

このトピックの質問に答えるために、Linuxでは次のようにstdinの「名前」を見つけることができます。

readlink -f /dev/stdin

例:

$ readlink -f /dev/stdin < a
/home/chazelas/a
$ : | readlink -f /dev/stdin
/proc/20238/fd/pipe:[758683]

(上記の20238はpidなので、readlinkシャットダウン後にパスはあまり使用されませんreadlink。とにかくそうではありません。これはpipe:[758683]情報提供のみであり、使用できません。開いている)。

より一般的にlsof可能な場合:

lsof -ad0 -p "$$" -Fn 2> /dev/null | sed -n 'n;s/^n//p'

(ただし、$$シェルを実行するプロセスのpidなので標準入力がリダイレクトされるサブシェルでは何の効果もない)

これで、読み取るためにファイルを再度開くことはできなくなりますが、それでもファイルを読み込んでも同じデータが再提供されないことがあります(たとえば、パイプを考えてみてください)。

$ seq 3 > a
$ { cat; cat /dev/stdin; } < a
1
2
3
1
2
3
$ cat a | { cat; cat /dev/stdin; }
1
2
3

Linuxで/dev/stdinstdinを開くのが通常のファイルの場合、ファイルは最初から読み直されますが、他のシステムでは/ dev / stdinを開く方が似ていますdup(0)。つまり、ファイルを最初から戻すことはありません。上記の最初の例では、1\n2\n3\n2回ではなく1回出力されます。

おすすめ記事