将输出打印到3个单独的列


26
MYPATH=/var/www/html/error_logs/
TOTALFILE=$(ls $MYPATH* | wc -l)
FILETIME=$(stat --format=%y $MYPATH* | head -5 | cut -d'.' -f1)  
FILE=$(ls -1tcr $MYPATH* | head -5 | rev | cut -d/ -f1 | rev)
TOPLINE=$(head -1 $MYPATH* | grep -Po '".*?"' | head -5)

我如何优雅地将这5个文件信息打印到带有标题的列中?

FILE CREATED TIME   | FILE NAME        | ERROR HEADER
---------------------------------------------
$FILETIME           | $FILE            | $TOPLINE
2012-11-29 11:27:45 | 684939947465     | "SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)"

等等5个文件

total files: $TOTALFILE

有什么简单的方法可以得到我想要的东西吗?

注意:当回显每个变量时,我得到的输出

2012-11-29 11:27:45 2012-11-29 11:27:41 2012-11-28 23:33:01 2012-11-26 10:23:37 2012-11-19 22:49:36
684939947465 1313307654813 1311411049509 1234980770182 354797376843
"SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)" "SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)" "Connection to localhost:6379 failed: Connection refused (111)" "An error occurred connecting to Redis." "SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)"

您对问题有三个答案,这些答案都可以解决您提出的问题。您应该更精确地了解要获得特定答案的内容。
Bernhard

Answers:


25

您可以使用shell命令'column'来检查:columnMAN page

将此与循环结合使用,您就可以从事业务,例如:

#!/bin/sh

MYPATH=/
TOTALFILE=$(ls $MYPATH/* | wc -l)
FILE=$(ls -1tcr $MYPATH/* | head -5 | rev | cut -d/ -f1 | rev)

declare -a FILES
declare -a FILETIME

OUTPUT="FILENAME CREATED TIME ERROR_HEADER\n\n------------------------------ ----------------------------- ----------------------------------- ------$

for i in $MYPATH/*;
do
    FILES[${#FILES[@]}]="$i"
    FILETIME[${#FILETIME[@]}]=$(stat --format=%y $i | head -5 | cut -d'.' -f1)
    TOPLINE=$(head -1 $i | grep -Po '".*?"' | head -5)

    OUTPUT="$OUTPUT\n${FILES[${#FILES[@]}-1]} ${FILETIME[${#FILETIME[@]}-1]} $TOPLINE\n"
done

echo -ne $OUTPUT | column -t

我需要进一步控制进入哪一列的内容,因此我在'*'上拆分了列,并使用了类似sed 's/^/ \* \*/g'的方法将内容从第一列转换为第三列。为我工作了。
LOAS

28

我建议使用printf,例如:

printf "%-30s | %-30s | %-30s" "$FILETIME" "$FILE" "$TOPLINE"

where %-30s 表示为string类型的输入参数保留30个字符。的-表示左对齐。


2

我会去一个循环

printf " %-20s | %-20s | %-20s\n " FILE\ CREATED\ TIME FILE\ NAME ERROR\ HEAD
for i in "$MYPATH"/*
do
    printf "%-20s | %-20s | %-20s\n " $FILENAME $FILE $TOPLINE
done
printf "Total Files: %s" $TOTALFILES 

我给你怎么不解决。现在,您需要调整代码,以便在循环内部处理FILENAME FILE和TOPLINE,而不是在循环之前进行处理。
BitsOfNix 2012年

您需要引用所有扩展,否则将很容易中断。
克里斯·

2

不知道这是您要做什么,unix中的“粘贴”是否可以将文件排列在列中,您可能需要printf来重新格式化sttdout。例:

柱


3
欢迎来到U&L,请不要以文字形式发布图片,您可以轻松复制/粘贴。
Archemar'5

1
我同意-复制并粘贴。我还无法投票,因此请发表评论
-KolonUK

1

@qnimbus答案可能最适合Linux系统,但在Sun或IBM上(如果您不足够/很幸运在2019年使用一个),此命令可能不可用。相反,您可以使用pr命令来获得相同的效果。在链接页面上的示例中,可以使用以下内容:

pr -3 word.lst | qprt

word.lst3列打印文件。就是说,这仅是解决您的问题的一部分,其余的我将由@qnimbus回答。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.