datamesh
ファイルの行列を変更するなどのツールがありますが、csv
文字に基づいて行と列を変更したいと思います。だからファイル
abcde
fghij
klmn
opqrs
しなければならない
afko
bglq
chmq
dinr
ej s
3行が短いので、最後の行にスペースを挿入する必要があることに注意してください。
もちろん、これを行うためにCプログラムを書くこともできますが、これを行うツールを見つけたことがありましたが、検索エンジンがそのツールを見つけるのを助けることはできませんでした。
答え1
rs
純粋なtranspose()モードでユーティリティを使用してこれを行うことができます-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
出力マージン幅(列間隔)を0に設定
awk
あるいは、入力分割には、空の入力フィールド区切り記号とデフォルトの出力フィールド区切り記号を使用します。
awk '{$1=$1} 1' FS= file | rs -Tng0
答え2
awk transposeを使用した一般的な解決策は次のとおりです。
正しく機能するには、列数が必要です。
これは、ファイルを値の配列として読み取るときに見つけることができます。
#!/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 は文字区切りを担当します。変数も空の場合、
文字は1行に印刷されます。sep
利用可能なawkが古い場合、null FSは効果がありません。次の 2 つのコマンドを使用します。
文字数を計算するには、以前のバージョンの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"
最新の awk の 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
1つの迷惑なのは、始める前に熱がいくつあるかを知る必要があることです。
答え4
行の文字数が少ない場合は、各行をいくつかの文字で埋め、余分な文字を削除します。
echo abc | sed 's/./&@@@@/' sed -r 's/(.{4})./\1/'
アルファベット@
echo ""| sed's/./&@@@@/'| sed -r's/(.{4})./\1/'
@@@@