bash - ファイルから入力行を読み取り、削除

bash - ファイルから入力行を読み取り、削除

このbashスクリプトがあります。

#!/usr/bin/env bash

DOMAINS=( '.com' '.co' )

while read input; do
  for (( i=0;i<${#DOMAINS[@]};i++)); do
  MATCH=$(whois "$input${DOMAINS[$i]}" | grep -oPa '^.*\b(Creation Date)\b.*$')
  if [ $? -eq 0 ]; then
    echo -e "$input${DOMAINS[$i]}\tregistered\t"$(date +%y/%m/%d_%H:%M:%S)"\t$MATCH" | tr '\n' '\t' |& tee --append output/registered.txt
    echo "" |& tee --append output/registered.txt
  else
    echo -e "$input${DOMAINS[$i]}\tavailable\t"$(date +%y/%m/%d_%H:%M:%S)"\t$MATCH" | tr '\n' '\t' |& tee --append output/available.txt
    echo "" |& tee --append output/available.txt
  fi
  done
done < "$1"

input.txt は次のようになります。

domain1
domain2
domain3

コンソールに戻ります。

$ ./script.sh input.txt
$ domain1.com    registered  Creation date: 15-jan-2015
$ domain1.co     available  Creation date: 15-jan-2015
$ domain2.com     registered  Creation date: 15-jan-2015
$ domain2.co      registered  Creation date: 15-jan-2015
$ domain3.com     registered  Creation date: 15-jan-2015
$ domain3.co      registered  Creation date: 15-jan-2015

input.txtから読み取った行を削除するには、このスクリプトをどのように変更する必要がありますか?

ご協力ありがとうございます!

編集する:

Casのソリューションは次のとおりです。

#!/bin/bash

DOMAINS='.com .co' # simple, space-separated list of domain suffixes

while read input; do
  for d in $DOMAINS; do
    MATCH=$(whois "$input$d" | grep -oPa '^.*\b(Creation Date)\b.*$')

    if [ $? ] ; then regavail="registered" ; else regavail="available" ; fi

    # what's the `tr` for below? is it really needed?
    # Is $MATCH really going to have more then one line in it?
    out=$(printf '%s\t%s' "$(date +%y/%m/%d_%H:%M:%S)" "$MATCH" | tr '\n' '\t')

    printf '%s\t%s\t%s\n' "$input$d" "$regavail" "$out" |& tee --append "output/$regavail.txt"

    seen+="$input\|"
  done
done < "$1"
seen=$(printf '%s' "$seen" | sed -e 's/\\|$//')
sed -i -e "/^\($seen\)$/d" "$1"

これは素晴らしいですが、スクリプトが完全に完了した後にのみこの行を削除します。 CTRL + Cを使用してスクリプトを終了するときにこの行を削除する方法はありますか?

CTRL + Cを「キャッチ」(ここで使用するのに良い用語である場合)し、スクリプトがinput.txtの最後の行に達した場合などのシグナルを送信するにはどうすればよいですか?処理された行は削除されますか、それとも処理されていない行を含むinput.txtファイル全体が削除されますか?

修正する:

input-cache.txtリアルタイムでファイルを生成し、使用された行を削除するバージョンは次のとおりです。input-cache.txt存在しない場合はinput.txtそのままにしてください。したがって、最初の起動時にinput.txtこのファイルのすべての内容をにコピーしますinput-cache.txt。スクリプトはから読み取られますが、コマンドはinput.txtリアルタイムsedでミラーからその行を削除し続けますinput-cache.txt。スクリプトを初めて起動する場合です。しかし、CTRL + Cを使用してスクリプトの実行を停止するとどうなりますか?この場合、すべての内容がinput.txt再び反転され、input-cache.txt同様に処理されていない行のみが残りますinput-cache.txt。 1つの欠点は、新しい行を追加するinput.txtと、次回の起動時にすぐに削除されることです。また、スクリプトのファイルはハードコードされています。 fire upコマンドを使用して指定した入力ファイルを呼び出す方法がわかりません./script.sh files/input.txt

input.txtスクリプトを再起動するときにキャッシュファイルを再構築するよりも、キャッシュファイルを生成するより良い方法があるかもしれません。

#!/bin/bash

# USAGE
# ./script.sh files/input.txt

cat files/input-cache.txt > files/input.txt
cat files/input.txt > files/input-cache.txt

DOMAINS='.com'

while read -r input; do
  for d in $DOMAINS; do
    MATCH=$(whois "$input$d" | grep -oPa '^.*\b(Creation Date)\b.*$')
    if [ $? -eq 0 ]; then
      echo "" |& tee --append files/registered.txt
      echo -e "$input$d\tregistered\t"$(date +%y/%m/%d_%H:%M:%S)"\t$MATCH" | tr '\n' '\t' |& tee --append files/registered.txt
    else
      echo "" |& tee --append files/available.txt
      echo -e "$input$d\tavailable\t"$(date +%y/%m/%d_%H:%M:%S)"\t$MATCH" | tr '\n' '\t' |& tee --append files/available.txt
    fi
  done
  sed -i "/$input/d" files/input-cache.txt
done < "$1"

答え1

fiと最初の行の間に次の行を追加しますdone

seen+="$input\|"

次に、最後の行の後にdone次の行を追加します。

seen=$(printf '%s' "$seen" | sed -e 's/\\|$//')
sed -i -e "/^\($seen\)$/d" "$1"

その後、入力ファイル(「$ 1」)で確認および処理されたすべてのドメインを含む正規表現を作成し、そのファイルからそのドメインをすべて削除します。

使用しているバージョンが()オプションをsedサポートしていない場合は、一時ファイルを代わりに使用できます。-i--in-place

tf=$(mktemp)
sed -e "/^\($seen\)$/d" "$1" > "$tf" && mv -f "$tf" "$1" || rm -f "$tf"

以下は、よりシンプルで読みやすくメンテナンスが簡単なスクリプトバージョンです。

#!/bin/bash

DOMAINS='.com .co' # simple, space-separated list of domain suffixes

while read input; do
  for d in $DOMAINS; do
    MATCH=$(whois "$input$d" | grep -oPa '^.*\b(Creation Date)\b.*$')

    if [ $? ] ; then regavail="registered" ; else regavail="available" ; fi

    # what's the `tr` for below? is it really needed?
    # Is $MATCH really going to have more then one line in it?
    out=$(printf '%s\t%s' "$(date +%y/%m/%d_%H:%M:%S)" "$MATCH" | tr '\n' '\t')

    printf '%s\t%s\t%s\n' "$input$d" "$regavail" "$out" |& tee --append "output/$regavail.txt"

    seen+="$input\|"
  done
done < "$1"
seen=$(printf '%s' "$seen" | sed -e 's/\\|$//')
sed -i -e "/^\($seen\)$/d" "$1"

関連情報