解析命令的输出,并存储在var中

时间:2018-12-18 00:40:52

标签: bash

我有一个要运行的命令:

echo "Performing unicornscan on:" $target
unicornscan -Ivv $target:1-65535 | tee enum/uniscan-alltcp.txt

这将产生如下输出:

TCP open 192.168.0.102:443  ttl 128
connected 192.168.103.227:54487 -> 192.168.0.102:161
TCP open 192.168.0.102:161  ttl 128
connected 192.168.103.227:47765 -> 192.168.0.102:80
TCP open 192.168.0.102:80  ttl 128
connected 192.168.103.227:4267 -> 192.168.0.102:1884
TCP open 192.168.0.102:139  ttl 128
sender statistics 963.9 pps with 65536 packets sent total
listener statistics 131180 packets recieved 0 packets droped and 0 interface drops
TCP open                http[   80]     from 192.168.0.102  ttl 128
TCP open         netbios-ssn[  139]     from 192.168.0.102  ttl 128
TCP open                snmp[  161]     from 192.168.0.102  ttl 128
TCP open               https[  443]     from 192.168.0.102  ttl 128
TCP open        microsoft-ds[  445]     from 192.168.0.102  ttl 128 

如何解析此输出以获取逗号分隔列表中的所有IP地址,例如: 80,139,161,443,445

谢谢

2 个答案:

答案 0 :(得分:1)

我写了一个脚本,可以解决您的问题。这将打印所有输出。

请按照以下步骤操作:

  1. 在文本编辑器中打开answer.bash(或任何想要给脚本命名的东西)。

  2. 键入或粘贴以下内容:

脚本:

#!/bin/bash

# Store the command in a variable for easy changes
# Note: The command is not actually executed until the while loop
COMMAND="unicornscan -Ivv $target:1-65535 | tee enum/uniscan-alltcp.txt"

PORTS=()

# For each line:
while read line; do
        # The third token is either IP or protocol name with '['
        token=`echo $line | awk '{print $3}'`
        last_char_idx=$((${#token}-1))
        last_char=${token:$last_char_idx:1}
        # Case 1: It is the protocol name
        if [[ "$last_char" = "[" ]]; then
                # This is a protocol. Therefore, port is token 4
                port=`echo $line | awk '{print $4}'`
                # Shave off the last character
                port=${port::-1}
        else
                # token is ip:port. Awk out the port
                port=`echo $token | awk -F: '{print $2}'`
        fi
        PORTS+=("$port")
done < <($COMMAND | egrep "^TCP open")
# egrep is used to skip any lines that don't begin with TCP open
# 'tee' should still send full output to file

# Print all the ports we found
for p in "${PORTS[@]}"; do
        echo -n "$p, "
done
echo
  1. 保存文件。

  2. 键入bash answer.bash。观察您希望的输出(希望如此!)

说明

该脚本使用while循环逐行浏览命令。每次迭代时,当前行都设置为line变量。

在while循环中,我使用egrep获得仅以TCP open开头的行。我注意到每行的第三个标记要么包含IP:Port值,要么包含协议名称,后跟[字符。脚本假定后一种情况以[结尾,并使用awk从第四个令牌中获取端口名,从而进行相应的处理。如果是IP:端口对,则也可以使用awk作为字段分隔符的:

以这种方式获得的每个端口都存储在PORTS阵列中。在脚本末尾,将打印ports数组的每个值,并产生以下输出:

443, 161, 80, 139, 80, 139, 161, 443, 445,

您可以将此脚本的输出传递到文件或变量中,或将其存储在脚本内部的变量中。

如果您有任何疑问,请告诉我它的工作原理。另外,我还要为过度使用subshel​​l表示歉意。

答案 1 :(得分:0)

尝试类似的东西:

#!/bin/bash

declare -a ary
while read -r line; do
    if [[ "$line" =~ \[\ *([0-9]+)\] ]]; then
        ary+=("${BASH_REMATCH[1]}")
    fi
done < "file.txt"

ifs_bak="$IFS"  # back up IFS
IFS=,; list="${ary[*]}"
IFS="$ifs_bak"  # retrieve IFS

echo "$list"
  • 正则表达式提取介于[]之间的数值,并为其分配${BASH_REMATCH[1]}
  • 然后将值存储在数组ary中。
  • 最后ary打印为逗号分隔的值。