wno*_*ise 17 software-rec text-processing
我正在编辑一个简单的表格。我想把它格式化得很好。虽然我可以使用tbl、latex或类似的东西,但这似乎有点矫枉过正——纯文本真的就足够了。由于它很简单,我不妨将源作为输出。所以来源也应该看起来不错。这似乎应该是一项完美的工作column -s '|' -t——它找到分隔符并自动插入空格以根据每列中的最大宽度对齐。不幸的是,它删除了分隔符,所以我无法在进一步编辑后重新运行它。是否有任何好的文本处理工具可以幂等地执行此操作,以便将其输出用作输入?还是我需要自己写?
编辑:这是我想要的一个例子:
foo | bar | baz
abc def | 12 | 23456
Run Code Online (Sandbox Code Playgroud)
应该成为
foo | bar | baz
abc def | 12 | 3456
Run Code Online (Sandbox Code Playgroud)
当' '分离器和间隔器同时使用时,column -t效果很好。但是我的物品中有空格,所以我不能使用它。使间隔物与分隔物不同会使事情复杂化。我认为在分隔符旁边将它们视为分隔符是很有用的,但事实并非column -s '|' -t如此(尽管显然当前的行为也很有用)。
hmo*_*liu 18
不知道我是否理解正确你的问题是什么。但是,可以通过添加额外的时间分隔符来解决吗?因此您可以使用第二个分隔符来标记分隔符,保持原始分隔符不变。
请参阅此示例,其中我将“@”添加到每个“|” 所以列命令的输入将是“xxx @| yyyy”。列将处理保留“|”的“@” 未受影响:
~$ echo "foo | this is some text | bar" | sed 's/|/@|/g' | column -s '@' -t
foo | this is some text | bar
Run Code Online (Sandbox Code Playgroud)
don*_*sti 15
这在您提出问题时不可用,但从2.23 版 column开始util-linux,您可以通过以下方式选择输出分隔符
-o, --output-separator string
Specify the columns delimiter for table output (default is two spaces).
Run Code Online (Sandbox Code Playgroud)
所以只需运行:
column -s '|' -o '|' -t infile
Run Code Online (Sandbox Code Playgroud)
这是一个 bash 脚本。它不使用“column -t”,并且分隔符的处理方式与 IFS 完全一样,因为它是 IFS(或者至少是 awk 的 IFS 内部版本)......默认分隔符是 $' \t'
此脚本完全填充最右侧的字段。
“列”不这样做。
通过填充所有列,可以
轻松修改此脚本以创建表格框架。
笔记。输入文件需要处理两次
(“列”也需要这样做)
第一遍是获取列的最大宽度。
第二遍是扩展字段(每列)
添加了一些选项并修复了一个明显的错误(重命名变量:(
#!/bin/bash
#
# script [-F sep] [file]
#
# If file is not specified, stdin is read
#
# ARGS ######################################################################
l=;r=;L=;R=;O=;F=' ' # defaults
for ((i=1;i<=${#@};i++)) ;do
case "$1" in
-- ) shift 1;((i--));break ;;
-l ) l="-l";shift 1;((i-=1)) ;; # left strip whitespace
-r ) r="-r";shift 1;((i-=1)) ;; # right strip whitespace
-b ) l="-l";r="-r";shift 1;((i-=1)) ;; # strip both -l and -r whitespace
-L ) L="-L";shift 1;((i-=1)) ;; # Left output delimiter is added
-R ) R="-R";shift 1;((i-=1)) ;; # Right output delimiter is added
-B ) L="-L";R="-R";shift 1;((i-=1)) ;; # output Both -L and -R delimiters
-F ) F="$2";shift 2;((i-=2)) ;; # source separator
-O ) O="$2";shift 2;((i-=2)) ;; # output separator. Default = 1st char of -F
-* ) echo "ERROR: invalid option: $1" 1>&2; exit 1 ;;
* ) break ;;
esac
done
#
if [[ -z "$1" ]] ;then # no filename, so read stdin
f="$(mktemp)"
ifs="$IFS"; IFS=$'\n'; set -f # Disable pathname expansion (globbing)
while read -r line; do
printf "%s\n" "$line" >>"$f"
done
IFS="$ifs"; set +f # re-enable pathname expansion (globbing)
else
f="$1"
fi
[[ -f "$f" ]] || { echo "ERROR: Input file NOT found:" ;echo "$f" ;exit 2 ; }
[[ -z "$F" ]] && F=' ' # input Field Separator string
[[ -z "$O" ]] && O="$F" # output Field Separator
O="${O:0:1}" # use single char only
# MAIN ######################################################################
max="$( # get max length of each field/column, and output them
awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" '
BEGIN { if (F!="") FS=F }
{ for (i=1;i<=NF;i++) {
if (l=="-l") { sub("^[ \t]*","",$i) }
if (r=="-r") { sub("[ \t]*$","",$i) }
len=length($i); if (len>max[i]) { max[i]=len }
if (i>imax) { imax=i }
}
}
END { for(i=1;i<=imax;i++) { printf("%s ",max[i]) } }
' "$f"
)"
awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" -v_max="$max" '
BEGIN { if (F!="") FS=F; cols=split(_max,max," ") }
{ # Bring each field up to max len and output with delimiter
printf("%s",L=="-L"?O:"")
for(i=1;i<=cols;i++) { if (l=="-l") { sub("^[ \t]*","",$i) }
if (r=="-r") { sub("[ \t]*$","",$i) }
printf("%s%"(max[i]-length($i))"s%s",$i,"",i==cols?"":O)
}
printf("%s\n",R=="-R"?O:"")
}
' "$f"
# END #######################################################################
if [[ -z "$1" ]] ;then # no filename, so stdin was used
rm "$f" # delete temp file
fi
exit
Run Code Online (Sandbox Code Playgroud)