ファイル名パラメータを使用するか、stdin、stdoutをデフォルトとして使用する方法(簡単)

ファイル名パラメータを使用するか、stdin、stdoutをデフォルトとして使用する方法(簡単)

bashスクリプトでファイル名をパラメータとして扱い、0、1、または2つのパラメータを入力および出力ファイル名として使用する、より明確で柔軟な方法が必要です。

  • args = 0 の場合、stdin から読み込み、stdout に書き込みます。
  • args = 1の場合、$ 1から読み込み、stdoutに書き込みます。
  • args = 2の場合、$ 1から読み込み、$ 2を書き​​込みます。

Bashスクリプトのバージョンをより明確で短くするにはどうすればよいですか?

これが私が今持っているものです。動作しますが、きれいではありません。

#!/bin/bash
if [ $# -eq 0 ] ; then #echo "args 0"
    fgrep -v "stuff"
elif [ $# -eq 1 ] ; then #echo "args 1"
    f1=${1:-"null"}
    if [ ! -f $f1 ]; then echo "file $f1 dne"; exit 1; fi
    fgrep -v "stuff" $f1 
elif [ $# -eq 2 ]; then #echo "args 2"
    f1=${1:-"null"}
    if [ ! -f $f1 ]; then echo "file $f1 dne"; exit 1; fi
    f2=${2:-"null"}
    fgrep -v "stuff" $f1 > $f2
fi

Perlのバージョンはよりきれいです。

#!/bin/env perl
use strict; 
use warnings;
my $f1=$ARGV[0]||"-";
my $f2=$ARGV[1]||"-";
my ($fh, $ofh);
open($fh,"<$f1") or die "file $f1 failed";
open($ofh,">$f2") or die "file $f2 failed";
while(<$fh>) { if( !($_ =~ /stuff/) ) { print $ofh "$_"; } }

ベストアンサー1

もっと使いますI/O リダイレクト:

#!/bin/bash
[[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1
[[ $1 ]] && exec 3<$1 || exec 3<&0
[[ $2 ]] && exec 4>$2 || exec 4>&1
fgrep -v "stuff" <&3 >&4

説明する

  • [[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1

    入力ファイルがコマンドライン引数として指定されているかどうか、およびファイルが存在するかどうかをテストします。

  • [[ $1 ]] && exec 3<$1 || exec 3<&0

    設定されている場合$1、つまり入力ファイルが指定されている場合は、指定されたファイルがファイル記述子で開き、3そうでない場合はstdinファイル記述子で繰り返されます3

  • [[ $2 ]] && exec 4>$2 || exec 4>&1

    同様に$2設定されている場合、つまり出力ファイルが指定されている場合、指定されたファイルはファイル記述子で開き4、それ以外の場合はstdoutファイル記述子で繰り返されます4

  • fgrep -v "stuff" <&3 >&4

    最後にfgrep呼び出され、それと以前に設定されたファイル記述子とstdinそれぞれにリダイレクトされます。stdout34

標準入力と出力の再オープン

中間ファイルディスクリプタを開かない場合は、そのstdinファイルディスクリプタを指定された入力ファイルと出力ファイルに直接置き換えることができますstdout

#!/bin/bash
[[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1
[[ $1 ]] && exec 0<$1
[[ $2 ]] && exec 1>$2
fgrep -v "stuff"

このアプローチの欠点は、スクリプト自体の出力とリダイレクト先のコマンドの出力を区別できないことです。元の方法では、スクリプト出力を変更されていないstdinsum として指定できました。stdoutこれは最終的にスクリプト呼び出し元によってリダイレクトされた可能性があります。指定された入出力ファイルはスクリプトstdinstdout

おすすめ記事