BASH 输出列格式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26130909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
BASH output column formatting
提问by aLee788
First time posting. HELLO WORLD. Working on my first script that just simply checks if a list of my websites are online and then returns the HTTP code and the amount of time it took to return that to another file on my desktop.
第一次发帖。你好,世界。处理我的第一个脚本,它只是简单地检查我的网站列表是否在线,然后返回 HTTP 代码以及将其返回到桌面上另一个文件所需的时间。
-- THIS SCRIPT WILL BE RUNNING ON MAC OSX --
-- 此脚本将在 MAC OSX 上运行 --
I would like to amend my script so that it formats its output into 3 neat columns.
我想修改我的脚本,以便将其输出格式化为 3 个整齐的列。
currently
目前
#!/bin/bash
file="/Users/USER12/Desktop/url-list.txt"
printf "" > /Users/USER12/Desktop/url-results.txt
while read line
do
printf "$line" >> /Users/USER12/Desktop/url-results.txt
printf "\t\t\t\t" >> /Users/USER12/Desktop/url-results.txt
curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line" >> /Users/USER12/Desktop/url-results.txt
printf "\n" >> /Users/USER12/Desktop/url-results.txt
done <"$file"
which outputs in the following format
它以以下格式输出
google.com 200 0.389
facebook.com 200 0.511
abnormallyLongDomain.com 200 0.786
but i would like to format into neat aligned columns for easy reading
但我想格式化成整齐对齐的列以便于阅读
DOMAIN_NAME HTTP_CODE RESPONSE_TIME
google.com 200 0.389
facebook.com 200 0.511
abnormallyLongDomain.com 200 0.486
Thanks for the help everyone!!
谢谢大家的帮助!!
回答by John1024
column
is very nice. You are, however, already using printf
which gives you fine control over the output format. Using printf
's features also allows the code to be somewhat simplified:
column
是非常好的。但是,您已经在使用printf
它,可以很好地控制输出格式。Usingprintf
的特性还允许代码稍微简化:
#!/bin/bash
file="/Users/USER12/Desktop/url-list.txt"
log="/Users/USER12/Desktop/url-results.txt"
fmt="%-25s%-12s%-12s\n"
printf "$fmt" DOMAIN_NAME HTTP_CODE RESPONSE_TIME > "$log"
while read line
do
read code time < <(curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line")
printf "$fmt" "$line" "$code" "$time" >> "$log"
done <"$file"
With the above defined format, the output looks like:
使用上面定义的格式,输出看起来像:
DOMAIN_NAME HTTP_CODE RESPONSE_TIME
google.com 301 0.305
facebook.com 301 0.415
abnormallyLongDomain.com 000 0.000
You can fine-tune the output format, such as spacing or alignment, by changing the fmt
variable in the script.
您可以通过更改fmt
脚本中的变量来微调输出格式,例如间距或对齐方式。
Further Refinements
进一步改进
The above code opens and closes the log file with each loop. This can be avoided as Charles Duffy suggests, simply by using exec
to redirect stdout
to the log file before the first printf
statement:
上面的代码在每个循环中打开和关闭日志文件。正如查尔斯·达菲 (Charles Duffy) 所建议的,这可以避免,只需在第一条语句之前使用exec
重定向stdout
到日志文件即可printf
:
#!/bin/bash
file="/Users/USER12/Desktop/url-list.txt"
exec >"/Users/USER12/Desktop/url-results.txt"
fmt="%-25s%-12s%-12s\n"
printf "$fmt" DOMAIN_NAME HTTP_CODE RESPONSE_TIME
while read line
do
read code time < <(curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line")
printf "$fmt" "$line" "$code" "$time"
done <"$file"
Alternatively, as Chepner suggests, the print statements can be grouped:
或者,正如 Chepner 建议的那样,打印语句可以分组:
#!/bin/bash
file="/Users/USER12/Desktop/url-list.txt"
fmt="%-25s%-12s%-12s\n"
{
printf "$fmt" DOMAIN_NAME HTTP_CODE RESPONSE_TIME
while read line
do
read code time < <(curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line")
printf "$fmt" "$line" "$code" "$time"
done <"$file"
} >"/Users/USER12/Desktop/url-results.txt"
An advantage of grouping is that, after the group, stdout is automatically restored to its normal value.
分组的一个好处是,分组后,stdout 会自动恢复到正常值。
回答by jm666
Shortened a bit
缩短了一点
#!/bin/bash
file="./url.txt"
fmt="%s\t%s\t%s\n"
( printf "$fmt" "DOMAIN_NAME" "HTTP_CODE" "RESPONSE_TIME"
while read -r line
do
printf "$fmt" "$line" $(curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line")
done <"$file" ) | column -t > ./out.txt
Don't need redirect every printf
but you can enclose the part of your script into (...)
and run it in an subshell a redirect it's output. Print every field separated with one tab and use the column
command to format it nicely.
不需要每次都重定向,printf
但您可以将脚本的一部分包含在其中(...)
并在子shell 中运行它作为重定向它的输出。打印用一个制表符分隔的每个字段,并使用该column
命令很好地对其进行格式化。
Anyway, usually is better don't put filenames (nor headers) into the script and reduce it to
无论如何,通常最好不要将文件名(或标题)放入脚本并将其减少到
#!/bin/bash
while read -r line
do
printf "%s\t%s\t%s\n" "$line" $(curl -o /dev/null --silent --head --write-out '%{http_code} %{time_total}' "$line")
done | column -t
and use it like:
并像这样使用它:
myscript.sh < url-list.txt >result.txt
this allows you use your script in pipes, like:
这允许您在管道中使用脚本,例如:
something_produces_urls | myscript.sh | grep 200 > somewhere.txt