我有这个 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"