2010-08-14 62 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

相關問題