テキストを1行ずつ処理し、各行から先行スペースを削除するのは簡単です。
$ LC_ALL=C git ls-files | sed -nE 's:^.*(\.[^./]+)$:\1:p' \
| sort | uniq -c | sort -snr > lines # create example "lines" file
$ cat lines # "lines" example file
30 .md
8 .png
4 .yml
1 .css
1 .gitignore
1 .ico
1 .sh
1 .txt
$ sed -Ee 's/^ +//' lines # removing leading spaces (U+0020)
30 .md
8 .png
4 .yml
1 .css
1 .gitignore
1 .ico
1 .sh
1 .txt
ただし、後続のすべての行を削除するために最初の行でのみスペースの数を設定する必要がある場合、これを達成するにはどうすればよいですか?出力は次のとおりです。
30 .md
8 .png
4 .yml
1 .css
1 .gitignore
1 .ico
1 .sh
1 .txt
私が達成したいのは、それをパイプで接続することです。コラム(1)出力をよりコンパクトにしますが、すべてのラインで水平間隔を維持します。シミュレーション:
$ column -x lines | expand -t 8
30 .md 8 .png 4 .yml
1 .css 1 .gitignore 1 .ico
1 .sh 1 .txt
今は左部分が切れずに空間を多く活用するようになりました。ユニーク(1)そして-氏右揃え番号(位置8)として追加するオプション。
最大数が固定されていると仮定する限り(たとえば、最大長が2桁)、ハードコーディングできます。
sed -Ee 's/^ {5}//' lines | column -x | expand -t 8
30 .md 8 .png 4 .yml 1 .css 1 .gitignore
1 .ico 1 .sh 1 .txt
答え1
Gnu sed: 先行スペースを保持に保存し、各行からこの数の先行スペースを削除します。行が示されているとおりに並べられているとします。
sed -Ee '
1{h;s/\S.*//;x;}
G;s/^(\s*)(.*)\n\1$/\2/
' file
awk '
NR==1 {
l0=length()
$1=$1
re = "^\\s{" l0-length() "}"
}
sub(re, "")+1
' file
perl -lpe '
$x //= do{/^\s*/g;+pos;};
$_ = substr($_,$x);
' file
答え2
調査をしなければなりませんでした。アーク(1)より早く。少なくとも最初の行の先頭のスペースの数を格納し、各行の書式を指定する小さなプログラムを作成できます。
$ awk '
NR==1 && match($0, /^ */) {p=RLENGTH+1};
{print(substr($0,p))}
' lines | column -x | expand -t 8
30 .md 8 .png 4 .yml 1 .css 1 .gitignore
1 .ico 1 .sh 1 .txt
答え3
なぜ最初の行に制限するのですか?ギガバイト単位のデータを処理する必要がない場合(すべてのデータをメモリに保存することは問題です)、最長の最初のフィールドを保存してそれを使用して残りの形式を指定できます。
$ cat lines
4 .yml
1 .sh
1 .ico
1 .gitignore
1 .css
30 .md
1 .txt
8 .png
そして:
$ awk -v l=0 '{
if(length($1)>l){
l=length($1)
}
a[$2]=$1
}
END{
for(line in a){
printf "%"l"s %s\n",a[line],line
}
}' lines
8 .png
1 .ico
1 .txt
1 .css
1 .sh
30 .md
1 .gitignore
4 .yml
だから:
$ awk -v l=0 '{ if(length($1)>l){l=length($1)} a[$2]=$1}END{for(line in a){printf "%"l"s %s\n",a[line],line}}' lines |
column -x | expand -t 8
8 .png 1 .ico 1 .txt 1 .css 1 .sh
30 .md 1 .gitignore 4 .yml
これが必要なく、最初の行にのみ興味がある場合は、次のように単純化できます。
$ perl -pe '/^(\s+)/; $l//=$1; s/^$l//' lines | column -x | expand -t 8
30 .md 4 .yml 1 .sh 1 .ico 1 .gitignore
1 .css 1 .txt 8 .png
答え4
理解して正しい道を行っていることを願っています。
$ sed 's/^[[:blank:]]//' file | cut -d' ' -f3- | column -x | expand -t 8 | cut -d' ' -f3-
30 .md 8 .png 4 .yml 1 .css 1 .gitignore
1 .ico 1 .sh 1 .txt
このようなシナリオでは、例えば次のようになります。
30 .md
8 .png
4 .yml
1 .css
1 .gitignore
4000 .ico
1 .sh
1 .txt
300 .foo
$ sed 's/^[[:blank:]]//' file | cut -d' ' -f3- | column -x | expand -t 8 | cut -d' ' -f3-
30 .md 8 .png 4 .yml 1 .css 4000 .ico
1 .gitignore 1 .sh 1 .txt 300 .foo