我对 bash 很陌生,我正在尝试通过创建一些小脚本来学习它。
我创建了一个小脚本来同时查找多个域的 DNS 条目。域作为属性给出。
COUNTER=0
DOMAINS=()
for domain in "$@"
do
WOUT_WWW=$(dig "$domain" +short)
if (( $(grep -c . <<<"$WOUT_WWW") > 1 )); then WOUT_WWW="${WOUT_WWW##*$'\n'}" ; fi
WITH_WWW=$(dig "www.${domain}" +short)
if (( $(grep -c . <<<"$WITH_WWW") > 1 )); then WITH_WWW="${WITH_WWW##*$'\n'}" ; fi
DOMAINS[$COUNTER]="$domain|$WOUT_WWW|$WITH_WWW"
COUNTER=$(($COUNTER+1))
done
现在我只想循环遍历新的“多维”数组并给出类似 mysql 表的输出:
+------------------------------+
| Row 1 | Row 2 | Row 3 |
+------------------------------+
| Value | Value | Value |
+------------------------------+
我怎样才能做到这一点?
答案1
使用perl
'sText::ASCIITable
模块(也支持多行单元格):
print_table() {
perl -MText::ASCIITable -e '
$t = Text::ASCIITable->new({drawRowLine => 1});
while (defined($c = shift @ARGV) and $c ne "--") {
push @header, $c;
$cols++
}
$t->setCols(@header);
$rows = @ARGV / $cols;
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$cell[$i][$j] = $ARGV[$j * $rows + $i]
}
}
$t->addRow(\@cell);
print $t' -- "$@"
}
print_table Domain 'Without WWW' 'With WWW' -- \
"$@" "${WOUT_WWW[@]}" "${WITH_WWW[@]}"
其中WOUT_WWW
和WITH_WWW
数组被构造为:
for domain do
WOUT_WWW+=("$(dig +short "$domain")")
WITH_WWW+=("$(dig +short "www.$domain")")
done
这使:
.---------------------------------------------------------------------.
| Domain | Without WWW | With WWW |
+-------------------+----------------+--------------------------------+
| google.com | 216.58.208.142 | 74.125.206.147 |
| | | 74.125.206.104 |
| | | 74.125.206.106 |
| | | 74.125.206.105 |
| | | 74.125.206.103 |
| | | 74.125.206.99 |
+-------------------+----------------+--------------------------------+
| stackexchange.com | 151.101.65.69 | stackexchange.com. |
| | 151.101.1.69 | 151.101.1.69 |
| | 151.101.193.69 | 151.101.193.69 |
| | 151.101.129.69 | 151.101.129.69 |
| | | 151.101.65.69 |
+-------------------+----------------+--------------------------------+
| linux.com | 151.101.193.5 | n.ssl.fastly.net. |
| | 151.101.65.5 | prod.n.ssl.us-eu.fastlylb.net. |
| | 151.101.1.5 | 151.101.61.5 |
| | 151.101.129.5 | |
'-------------------+----------------+--------------------------------'
答案2
我尝试了很多变化并做了一些研究。以下代码对我来说非常有用:
for DOMAIN in "${DOMAINS[@]}"; do
printf "%-8s\n" "${DOMAIN}"
done | sed -e 's/|/_|g' | column -t -s '_' | awk '1;! (NR%1){print "---------";}'
只是循环遍历我的数组。我使用它是sed
因为我的数组值中有一个分隔符来将它们分开。但这column
就是我所寻找的吗?
答案3
function printTable()
{
local -r delimiter="${1}"
local -r data="$(removeEmptyLines "${2}")"
if [[ "${delimiter}" != '' && "$(isEmptyString "${data}")" = 'false' ]]
then
local -r numberOfLines="$(wc -l <<< "${data}")"
if [[ "${numberOfLines}" -gt '0' ]]
then
local table=''
local i=1
for ((i = 1; i <= "${numberOfLines}"; i = i + 1))
do
local line=''
line="$(sed "${i}q;d" <<< "${data}")"
local numberOfColumns='0'
numberOfColumns="$(awk -F "${delimiter}" '{print NF}' <<< "${line}")"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]]
then
table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
fi
# Add Header Or Body
table="${table}\n"
local j=1
for ((j = 1; j <= "${numberOfColumns}"; j = j + 1))
do
table="${table}$(printf '#| %s' "$(cut -d "${delimiter}" -f "${j}" <<< "${line}")")"
done
table="${table}#|\n"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]] || [[ "${numberOfLines}" -gt '1' && "${i}" -eq "${numberOfLines}" ]]
then
table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
fi
done
if [[ "$(isEmptyString "${table}")" = 'false' ]]
then
echo -e "${table}" | column -s '#' -t | awk '/^\+/{gsub(" ", "-", $0)}1'
fi
fi
fi
}
function removeEmptyLines()
{
local -r content="${1}"
echo -e "${content}" | sed '/^\s*$/d'
}
function repeatString()
{
local -r string="${1}"
local -r numberToRepeat="${2}"
if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
then
local -r result="$(printf "%${numberToRepeat}s")"
echo -e "${result// /${string}}"
fi
}
function isEmptyString()
{
local -r string="${1}"
if [[ "$(trimString "${string}")" = '' ]]
then
echo 'true' && return 0
fi
echo 'false' && return 1
}
function trimString()
{
local -r string="${1}"
sed 's,^[[:blank:]]*,,' <<< "${string}" | sed 's,[[:blank:]]*$,,'
}
样品运行
$ cat data-1.txt
HEADER 1,HEADER 2,HEADER 3
$ printTable ',' "$(cat data-1.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
$ cat data-2.txt
HEADER 1,HEADER 2,HEADER 3
data 1,data 2,data 3
$ printTable ',' "$(cat data-2.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
| data 1 | data 2 | data 3 |
+-----------+-----------+-----------+
$ cat data-3.txt
HEADER 1,HEADER 2,HEADER 3
data 1,data 2,data 3
data 4,data 5,data 6
$ printTable ',' "$(cat data-3.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
| data 1 | data 2 | data 3 |
| data 4 | data 5 | data 6 |
+-----------+-----------+-----------+
$ cat data-4.txt
HEADER
data
$ printTable ',' "$(cat data-4.txt)"
+---------+
| HEADER |
+---------+
| data |
+---------+
$ cat data-5.txt
HEADER
data 1
data 2
$ printTable ',' "$(cat data-5.txt)"
+---------+
| HEADER |
+---------+
| data 1 |
| data 2 |
+---------+
参考库位于:https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash