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保持完整。因此,在第一次启动时,当 onlyinput.txt出现时,它会将此文件中的所有内容复制到input-cache.txt.脚本从 读取input.txt,但sed命令不断地、实时地从镜像的 中删除这些行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"

相关内容