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.txtsed명령은 실시간으로 미러에서 해당 줄을 계속 제거합니다 input-cache.txt. 스크립트를 처음 시작하는 경우입니다. 하지만 CTRL+C를 사용하여 스크립트 실행을 중지하면 어떻게 될까요? 이 경우 의 모든 내용이 input.txt다시 반전되어 input-cache.txt에서와 마찬가지로 처리되지 않은 행만 남게 됩니다 input-cache.txt. 한 가지 단점은 새 줄을 추가하면 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"

관련 정보