2010-08-14 96 views
0

我有一个像下面如何使用shell脚本对以下文件进行排序?

11:00AM JOHN STAMOS 1983-08-07 I like Pizza Hut 
12:00AM JACK SPARROW PIRATE 1886-09-07 I like Pizza Hut and DOminoz 
11:00AM SANTA 1986-04-01 I like cold beer 

我怎么排序日期列以上的文本文件?我面临的问题是由于可变长度名称列。有些人有第一个中间名,有些人只有第一个名字,等等。

回答

1
sed 's/\([0-9]\{4\}\(-[0-9]\{2\}\)\{2\}\)/|\1/' | sort -t '|' -k 2| sed s/'|'// 
+0

+1:我喜欢你的想法,添加一个替代分隔符到适当的位置。我认为这可能比我的回答更灵活。 – 2010-08-20 07:30:10

0
cat file.txt | python -c 'import re, sys; print "".join(sorted(sys.stdin, key=lambda x:re.findall("\d{4}-\d{2}-\d{2}",x)))' 
1

你需要做的是将日期复制到前面,然后排序默认情况下将使用整行作为排序键。然后再次删除日期。

我用sed将挑选出的一切行动,而我所在的公司NNNN-NNNN格式(最后)日期和日期复制到前面。

排序后,只需使用sed(或剪切-c11-会更容易)再次从正面删除日期。

这工作在Linux中:

sed 's/^\(.* \([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] \)\)/\2\1/' | 
sort | 
sed 's/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] //' 

,并提供:

12:00AM JACK SPARROW PIRATE 1886-09-07 I like Pizza Hut and DOminoz 
11:00AM JOHN STAMOS 1983-08-07 I like Pizza Hut 
11:00AM SANTA 1986-04-01 I like cold beer 

这适用于你的数据,但可以很容易变得相当尴尬,如果你的数据的变化(例如你有一个行多个日期)。

0

纯击:

declare -a array 
declare -a order 

IFS=$'\n' 
array=($(cat "$infile")) 

index=0 
for line in "${array[@]}"; do 
    [[ "$line" =~ ([[:digit:]]+)-([[:digit:]]+)-([[:digit:]]+) ]] 
    key="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}" 
    if [ -z "${order[key]}" ] ; then 
    order[key]="$index" 
    else 
    order[key]="${order[key]} $index" 
    fi 
    ((index++)) 
done < "$infile" 

IFS=' ' 
for key in ${order[*]}; do 
    printf "%s\n" "${array[key]}" 
done 

从日期生成指数,并用它们作为排序列表。

+0

如果多行有相同的日期,则失败。否则,它很聪明。 – 2010-08-14 13:42:08

+0

是的,你是对的。我刚刚改进了解决方案。 – 2010-08-14 17:04:17

相关问题