2

好吧,所以我大约一周前问了一个问题,关于如何使用 sed 或 awk 提取两个空白行之间的文本块,以及省略部分提取的文本。我得到的答案几乎满足了我的需求,但现在我正在做一些额外的事情来娱乐(为了强迫症)。

我想在这一轮中对 awk 的输出进行排序。我找到了这个问题和答案,但它并不能完全帮助我解决问题。我也尝试过大量的 awk 文档,试图弄清楚我该如何做到这一点,但无济于事。

所以这是我脚本中完成所有脏工作的代码块:

# This block of stuff fetches the nameservers as reported by the registrar and DNS zone
# Then it gets piped into awk to work some more formatting magic...
# The following is a step-for-step description since I can't put comments inside the awk block:
# BEGIN:
#     Set the record separator to a blank line
#     Set the input/output field separators to newlines
# FNR == 3:
#     The third block of dig's output is the nameservers reported by the registrar
#     Also blanks the last field & strips it since it's just a useless dig comment
dig +trace +additional $host | \
awk -v host="$host" '
    BEGIN {
        RS = "";
        FS = "\n"
    }
    FNR == 3 {
        print "Nameservers of",host,"reported by the registrar:";
        OFS = "\n";
        $NF = ""; sub( /[[:space:]]+$/, "" );
        print
    }
'

如果我google.com作为以下值传入$host(其他主机名可能会产生不同行数的输出),则输出如下:

Nameservers of google.com reported by the registrar:
google.com.         172800  IN  NS  ns2.google.com.
google.com.         172800  IN  NS  ns1.google.com.
google.com.         172800  IN  NS  ns3.google.com.
google.com.         172800  IN  NS  ns4.google.com.
ns2.google.com.         172800  IN  A   216.239.34.10
ns1.google.com.         172800  IN  A   216.239.32.10
ns3.google.com.         172800  IN  A   216.239.36.10
ns4.google.com.         172800  IN  A   216.239.38.10

这个想法是,使用现有的 awk 块,或将 awk 的输出管道化为更多 awk、排序或其他任何组合的组合,使用条件算法对该文本块进行排序:

if ( column 4 == 'NS' )
    sort by column 5
else // This will ensure that the col 1 sort includes A and AAAA records
    sort by column 1

我对答案的偏好与上一个问题几乎相同:

  1. 最重要的是,它必须是可移植的,因为我在使用 sed(在 OS X 上必须用 gsed 替换)和 grep 时遇到了 OS X(我的家庭系统)和 Fedora(我在工作中使用的)之间的不同行为 - m 标志(在另一个脚本中使用)
  2. 非常感谢对解决方案如何工作的解释,作为学习机会比其他任何事情都重要。我已经从上一个问题中提供的 awk 解决方案中学到了很多东西。
  3. 如果解决方案可以在同一个 awk 块中实现,那也很棒
  4. 如果不是,那么我可以通过管道 awk 的输出的简单而雄辩的东西就足够了
4

2 回答 2

1

这是基于@shellter 想法的解决方案。将您的名称服务器记录的输出通过管道传输到此:

awk '$4 == "NS" {print $1, $5, $0} $4 == "A" {print $1, $1, $0}' | sort | cut -f3- -d' '

解释:

  • 使用awk,我们只取NSandA记录,并重新打印带有前缀的同一行:主搜索列 + 辅助搜索列
  • sort将对行进行排序,这要归功于我们设置第一列和第二列的方式,顺序应该是你想要的
  • 随着cut我们摆脱了用于排序的前缀
于 2013-10-06T15:29:08.577 回答
0

我知道您询问了awk解决方案,但是由于您也对其进行bash了标记,因此我想我会提供这样的版本。它也应该比awk;)更便携

# the whole line
declare -a lines
# the key to use for sorting
declare -a keys

# insert into the arrays at the appropriate position
function insert
{
    local key="$1"
    local line="$2"
    local count=${#lines[*]}
    local i
    # go from the end backwards
    for((i=count; i>0; i-=1))
    do
        # if we have the insertion point, break
        [[ "${keys[i-1]}" > "$key" ]] || break
        # shift the current item to make room for the new one
        lines[i]=${lines[i-1]}
        keys[i]=${keys[i-1]}
    done
    # insert the new item
    lines[i]=$line
    keys[i]=$key
}

# This block of stuff fetches the nameservers as reported by the registrar and DNS zone
#     The third block of dig's output is the nameservers reported by the registrar
#     Also blanks the last field & strips it since it's just a useless dig comment
block=0
dig +trace +additional $host |
while read f1 f2 f3 f4 f5
do
    # empty line begins new block
    if [ -z "$f1" ]
    then
        # increment block counter
        block=$((block+1))
        # and read next line
        continue
    fi

    # if we are not in block #3, read next line
    [[ $block == 3 ]] || continue

    # ;; ends the block
    if [[ "$f1" == ";;" ]]
    then
        echo "Nameservers of $host reported by the registrar:"
        # print the lines collected so far
        for((i=0; i<${#lines[*]}; i+=1))
        do
            echo ${lines[i]}
        done
        # don't bother reading the rest
        break
    fi

    # figure out what key to use for sorting
    if [[ "$f4" == "NS" ]]
    then
        key=$f5
    else
        key=$f1
    fi
    # add the line to the arrays
    insert "$key" "$f1 $f2 $f3 $f4 $f5"
done
于 2013-10-06T15:30:07.287 回答