说我有一个sort_me.txt文件:
a
d
b
c
f
g
// dont mix the two sections
a
c
d
b
此刻,我做了显而易见的sort sort_me.txt
,我得到了:
a
a
b
b
c
c
d
d
// dont mix the two sections
f
g
当然这不是我想要的,我想要的是它在评论之前对部分进行排序,然后在评论之后单独对部分进行排序。
获得所需的结果:
a
b
c
d
f
g
// dont mix the two sections
a
b
c
d
答案 0 :(得分:2)
Perl救援:
perl -007 -nE '
@sections = map [ split /\n/ ], split m{^(?=//)}m;
say join "\n", sort @$_ for @sections;
' -- file
-007
读取整个文件而不是逐行处理(仅当文件不大时才有效)@sections
是一个数组数组,外部数组对应于各个部分,内部数组对应于各行如果文件太大而无法放入内存,则需要逐行处理,只存储当前部分:
perl -ne '
sub out { print sort @lines; @lines = $_ }
if (m{^//}) { out() }
else { push @lines, $_ }
END { out() }
' -- file
答案 1 :(得分:1)
如果没有perl,你可以使用这样的脚本来完成它:
#!/bin/bash
FILE_NAME=$1
SEPARATOR='//'
LINE_NUMBER=`grep -n $SEPARATOR $FILE_NAME | cut -f1 -d:`
FILE_LENGTH=`wc -l $FILE_NAME | cut -f1 -d\s`
head -$(($LINE_NUMBER-1)) $FILE_NAME | sort
grep $SEPARATOR $FILE_NAME
tail -$(($FILE_LENGTH-$LINE_NUMBER-1)) $FILE_NAME | sort
它搜索分隔线并逐个对这些部分进行排序。当然,如果你有两个以上的部分,它将不起作用。
答案 2 :(得分:1)
我在考虑使用csplit
将这些部分拆分为单独的文件,但当然应该有更简单的方法来实现这一目标:
#!/bin/bash
linenum=`csplit -z $1 /^$/ {*}`
count=0
output=''
for line in $linenum
do
file=`printf "xx%.2d" $count`
sorted=`cat $file | sort`
output="$output$sorted"
((count++))
done
echo "$output"
请注意,csplit
会为每个部分创建一个临时文件,因此您可以更新上述脚本以取消每个部分unlink $file
的链接。