-1

我有一个包含一长串序列的文件,这些序列是逗号分隔的数字列表。可以使用 注释掉列表#,例如

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

我想要一个 bash 命令,它采用第一个未注释的序列,拆分数字并将它们传递给一个命令(这是敲门,用于端口敲门),最后注释掉产生的行。

在上面的示例中第一次运行命令应该:

  1. knock myhost 7 8 9
  2. 将输入文件编辑为

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

我想有一些超级简单的方法可以使用 sed/awk 来做到这一点,但我不太了解这些命令。

先感谢您


编辑我希望一个命令只处理输入文件中的一行,而不是通过循环消耗整个文件


编辑2*

我最终用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
4

3 回答 3

1

听起来您本质上想要处理整个文件,但在发生中断时跟踪哪些行已经被处理。随着您的进行,我会将输入的注释版本写入第二个文件,当脚本出于任何原因退出时,将原始输入替换为临时输入。就像是

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
于 2016-10-17T18:06:52.600 回答
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
于 2016-10-17T18:34:30.670 回答
0

这个怎么样?

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

Perl 脚本执行替换,并将替换行中的值保存在数组中@p。当我们完成文件的编写后,我们通过函数将参数传递@p给。knocksystem()

当然,这可以在循环的中间执行,但在这种情况下,失败可能会损坏文件。也许你会想用类似的东西包装它

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

如果(或 Perl 脚本中的其他内容)失败,它会创建一个备份$file~并将其移回。system()

于 2016-10-18T04:29:15.847 回答