rs
rs
是一个 BSD 实用程序,它也随 macOS 一起提供,但它可以从其他平台上的包管理器中获得。它以 APL 中的 reshape 函数命名。
使用空格和制表符序列作为列分隔符:
rs -T
使用制表符作为列分隔符:
rs -c -C -T
使用逗号作为列分隔符:
rs -c, -C, -T
-c
更改输入列分隔符并-C
更改输出列分隔符。一个单独的-c
或-C
将分隔符设置为制表符。-T
转置行和列。
不要使用-t
代替-T
,因为它会自动选择输出列数,以便输出行填充显示的宽度(默认为 80 个字符,但可以使用 更改-w
)。
当使用 指定输出列分隔符-C
时,会在每行的末尾添加一个额外的列分隔符,但您可以使用 删除它sed
:
$ seq 4|paste -d, - -|rs -c, -C, -T
1,3,
2,4,
$ seq 4|paste -d, - -|rs -c, -C, -T|sed s/.\$//
1,3
2,4
这对于第一行以一个或多个空列结尾的表会失败,因为列数是根据第一行的列数确定的:
$ rs -c, -C, -T<<<$'1,\n3,4'
1,3,4,
呆呆
$ seq 4|paste -d, - -|awk '{for(i=1;i<=NF;i++)a[i][NR]=$i}END{for(i in a)for(j in a[i])printf"%s"(j==NR?"\n":FS),a[i][j]}' FS=,
1,3
2,4
这使用数组的数组,这是一个gawk
扩展。macOSnawk
从 2007 年开始提供不支持数组数组的版本。
要将空格用作分隔符而不折叠空格和制表符序列,请使用FS='[ ]'
.
红宝石
$ seq 4|paste -d, - -|ruby -e'STDIN.map{|x|x.chomp.split(",",-1)}.transpose.each{|x|puts x*","}'
1,3
2,4
禁用最后丢弃空字段的-1
参数:split
$ ruby -e'p"a,,".split(",")'
["a"]
$ ruby -e'p"a,,".split(",",-1)'
["a", "", ""]
功能形式:
$ tp(){ ruby -e's=ARGV[0];STDIN.map{|x|x.chomp.split(s==" "?/ /:s,-1)}.transpose.each{|x|puts x*s}' -- "${1-$'\t'}";}
$ seq 4|paste -d, - -|tp ,
1,3
2,4
s==" "?/ /:s
之所以在上面使用,是因为当split
函数的参数是单个空格时,它会启用类似 awk 的特殊行为,其中字符串基于空格和制表符的连续运行进行拆分:
$ ruby -e'p" a \tb ".split(/ /,-1)'
["", "a", "", "\tb", ""]
$ ruby -e'p" a \tb ".split(" ",-1)'
["a", "b", ""]
jq
tp(){ jq -R .|jq --arg x "${1-$'\t'}" -sr 'map(./$x)|transpose|map(join($x))[]';}
jq -R .
将每个输入行打印为 JSON 字符串文字,-s
( --slurp
) 在将每行解析为 JSON 后为输入行创建一个数组,并且-r
( --raw-output
) 输出字符串的内容而不是 JSON 字符串文字。运算符重载以/
拆分字符串。
R
$ printf %s\\n 1,2 3,4|Rscript -e 'write.table(t(read.table("stdin",sep=",")),"",sep=",",quote=F,col.names=F,row.names=F)'
1,3
2,4
如果您替换Rscript
为R
,它会将正在运行的代码回显到 STDOUT。如果在读取整个 STDIN 之前出现ignoring SIGPIPE signal
类似退出的命令,也会导致错误。head -n1
write.table
当输出文件的参数为空字符串时,打印到 STDOUT。