有一些工具,例如datamesh
在文件中转置矩阵csv
,但我想基于字符交换行和列。所以一个文件
abcde
fghij
klmn
opqrs
应该成为
afko
bglq
chmq
dinr
ej s
请注意,由于第 3 行较短,因此必须在最后一行插入一个空格。
当然,我可以编写一些 C 程序来做到这一点,但我想我曾经遇到过一个可以做到这一点的工具,但我的搜索引擎无法帮助我找到它。
答案1
rs
您可以使用纯转置 ( ) 模式下的实用程序来完成此操作-T
- 如果您首先适当地间隔输入,即
$ sed -e 's/./& /g' -e 's/ $//' file
a b c d e
f g h i j
k l m n
o p q r s
(或者,如果您有 GNU sed,则可以使用sed 's/./ &/2g'
;另一个选项是使用循环sed -E ':a; s/([^ ])([^ ])/\1 \2/; ta'
);然后
$ sed -e 's/./& /g' -e 's/ $//' file | rs -Tng0
afko
bglp
chmq
dinr
ej s
重要的选项是:
-T
纯转置-n
填充空条目-g0
将输出装订线宽度(列间距)设置为零
awk
或者,使用空输入字段分隔符和默认输出字段分隔符进行输入拆分:
awk '{$1=$1} 1' FS= file | rs -Tng0
答案2
使用 awk 转置的通用解决方案如下。
为了正确工作,我们需要列数。
在将文件读入值数组时可以找到这一点:
#!/bin/bash
file=i4
delimiter=""
sep=""
transpose() { : # comment sed for newer awks.
# Do this to separate characters in quite old awk
# very old wak does not allow that the FS could be Null.
#sed -e 's/./ &/g' "$file" |
awk '
{ for(i=1;i<=NF;i++){a[NR,i]=$i};{(NF>m)?m=NF:0} }
END { for(j=1; j<=m; j++)
{ for(i=1; i<=NR; i++)
{ b=((a[i,j]=="")?" ":a[i,j])
printf("%s%s",(i==1)?"":sep,b)
}
printf("\n")
}
}
' FS="$delimiter" sep="$sep" cc="$countcols" <"$file"
}
transpose
有了这个文件:
abc
fghij
klmn
opqrs
将打印:
afko
bglp
chmq
inr
j s
如果“字段分隔符”为空,awk 负责分隔字符。如果变量也为空,
则字符将打印在一行中。sep
如果可用的 awk 是较旧的,则 null FS 无效。使用以下两个命令。
要计算字符数,请在旧版 awks 中使用:
# Work with any POSIX awk to find the max character count in all rows.
countcols=$(awk '{l=length($0);(l>max)?max=l:0}END{print max}' < "$file")
要进行转置,可以在每个字符前面添加一个空格,并使用空格作为“字段分隔符”并避免空 FS:
sed -e 's/./ &/g' < "$file" |
awk ' {for(i=1;i<=cc;i++){if($i==""){$i=" "};r[i]=r[i]sep$i;};sep=""};
END{for(i=1;i<=cc;i++)print(r[i])}
' cc="$countcols"
注释较新 awks 的 sed 行。
答案3
这是一个带有cut
和 的解决方案paste
。由于您没有任何分隔符(例如空格或制表符),因此需要进行一些修复sed
:
for COL in {1..5}; do cut -c $COL < infile | paste -s -d_ ; done | sed -e 's/__/_ /g' -e 's/_//g'
这里分成多行:
for COL in {1..5}; do
cut -c $COL < infile | paste -s -d_
done | sed -e 's/__/_ /g' -e 's/_//g'
第一部分的输出如下所示:
for COL in {1..5}; do cut -c $COL < infile | paste -s -d_ ; done
a_f_k_o
b_g_l_p
c_h_m_q
d_i_n_r
e_j__s
一件烦人的事情是你必须在开始之前知道有多少列。
答案4
如果行字符较少,请用一些字符填充每行,然后删除多余的字符。
回声 abc | sed 's/./&@@@@/'| sed -r 's/(.{4})./\1/'
abc@
回声“”| sed's/./&@@@@/'| sed -r's/(.{4})./\1/'
@@@@