2016-10-17 4 views
-1

ファイルのリストは、カンマ区切りのリストです。リストは、#を使用してコメントアウトすることができます。ファイルを解析してコメントのついた最初の行を生成し、コメントを付けてその内容を使用するbashスクリプト

#1,2,3 
#4,5,6 
7,8,9 
10,11,12 

私は、最初のコメントのないシーケンスを取りbashコマンドをしたいのですが数字を分割し(ポートがノックに使用ノックで、)コマンドに渡し、最終的に得られた行をコメントアウト。

#1,2,3 
#4,5,6 
#7,8,9 
10,11,12 

として

  1. 実行knock myhost 7 8 9
  2. 編集入力ファイルを、私はいくつかのスーパーは、単にそこにあると思います。上記の例でコマンドを最初にすべき実行

    sed/awkを使ってこれを行う方法ですが、私はこれらのコマンドをあまりよく知っていません。

    は、事前にありがとう、私は、入力ファイルからのみ、単一の行を処理し、コマンドを望む編集


    、ループ


    EDIT2てファイル全体を消費しません*

    私はzshでこれを書いてしまいました。あなたのおかげで、

    #!/bin/zsh 
    sequences=$HOME/.knock.$1.sequences 
    read -A line <<< "$(grep "^[^#]" $sequences -m 1 -n)" 
    IFS=, read -A ports <<< $line[2] 
    IFS=: read -A linenum <<< $line[1] 
    
    knock $1 $ports 
    
    if nc -z -w1 $1 22; 
    then 
         sed -i "$linenum s/^/#/" $sequences 
    fi 
    
+1

ファイルを繰り返し書き直すと、隠された効率が悪くなります。単純にカウントを保持して、最初から多くの行がI/O( 'sed -i" 1、$ {count} s/^ /#/ "$ file" ')。それが受け入れられず、詳細な制御が絶対に必要な場合、シーケンシャルファイルはほとんど理想的ではありません。おそらくデータベースやキューシステムを使用していますか? – tripleee

+0

毎回実行されるコマンドが1行だけを処理したい。私はそのコマンドを頻繁に使用しません。 – leonixyz

+1

@leonixyz、あなたはプログラムがうまくいくと思う方法を表現するメタコードを書いてみてはいかがですか?それが立てば、あなたの質問は、人々が訂正するためのコードがないので、ダウンボートを集めるかもしれません。ここ数人はプロのプログラミングサービスを無償で提供していますが、実際にはStackOverflowの「方法」ではありません。私たちはあなたに無料のものを提供するだけでなく、工芸品の改善を手助けしたいと考えています。 – ghoti

答えて

1

それはあなたが基本的にファイル全体を処理するように聞こえるが、行はすでに中断が発生した場合に処理されているのを追跡します。何らかの理由でスクリプトが終了したときに元の入力を一時的なものに置き換えて、2番目のファイルにコメントのバージョンを書きます。ここで

trap 'mv tmp "$input"' EXIT 
while IFS= read -r line; do 
    [[ $line = #* ]] && continue # skip commented lines 
    IFS=, read -a arr <<< "$line" 
    knock "${arr[@]}" 
    echo "#$line" >&3 
done < "$input" 3> tmp 
+0

入力がカンマで区切られているので、 'IFS = 'を設定することがあります。 – tripleee

+0

私は2回目の 'read'でそれを行いました。これは、カンマでフィールドに再結合するのではなく、(コメント付きの)元の行をテンポラリファイルに書き出す最も簡単な方法でした。 – chepner

+0

このコードはファイル全体を消費します。おそらく私の質問はよく聞かれていませんでした。私は* one行だけを処理するコマンドが必要です。 – leonixyz

0

のようなものは、同じことを行うにはawkベースのソリューションです:

awk -v tf="$$.tmp" -F, '!done && !/^#/ { 
    r="#" $0 
    $1 = $1 
    cmd = "knock myhost " $0 
    while((cmd | getline) > 0) 
     print 
    close(s) 
    done = 1 
    $0 = r 
} 
{ 
    print > tf 
}' file && mv $$.tmp file 
0

このうどのように?

perl -i -aF',' -pe 'if (!$done and s/^(?!#)/#/) { $done=1; @[email protected] } 
    END { system("knock", @p) if $done }' "$file" 

Perlスクリプトは、置換を行い、アレイ@pで置換された行からの値を保持します。ファイルの書き込みが完了したら、関数を使用してにパラメータをknockに渡します。

これはループの途中で行うことができますが、その場合はエラーが発生してファイルが破損する可能性があります。おそらく、あなたはバックアップ$file~を作成し、system()(またはPerlスクリプトで何か他のもの)が失敗した場合に戻ってそれを動かす

perl -i~ -aF',' -pe 'if (!$done and s/^(?!#)/#/) { 
    $done=1; system("knock", @F); die "$!" if $? }' "$file" || 
mv "$file~" "$file" 

ようなもので、それをラップすることをお勧めします。

関連する問題