逐行处理文本,删除每行的前导空格很容易:
$ 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)与-C选项将它们添加为右对齐数字(在位置 8)。
只要我假设最大计数是固定的,例如最大长度为两位数,我就可以对其进行硬编码:
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
我应该一直在调查awk(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