在shell脚本中对多个非标准列进行排序

时间:2013-05-23 22:17:54

标签: bash shell sorting

我有一个完整路径的文件列表,我需要在bash shell中进行排序。

列表看起来像

/total/path/software/version1.2.3.4/filename.10.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.2.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.12.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.3.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.18.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.20.cfg -- infomation grepped
/real/path/software/version1.2.3.4/filename.4.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.5.cfg -- infomation grepped

我需要首先按路径排序列表,然后按文件名编号排序。

我试过了:

 sort -t'.' -k 1,1 -k 2,5n fileame.txt

但它只是在路上排序。如果我这样做:

sort -t'.' -k5n filename.txt

工作正常。在按路径排序后,如何按数字顺序获取文件名?

由于

3 个答案:

答案 0 :(得分:1)

这就是你要找的东西吗?

 Kaizen ~
 $ for ch in `sort testfile.txt | cut -c2-3 | uniq `
 > do
 > sed -n "/^\/$ch/p" testfile.txt | sort -t'.' -k5n ;
 > done ;

结果:

/full/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.3.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.12.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.20.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.2.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.18.cfg -- infomation grepped
/real/path/software/version1.2.3.4/filename.4.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.5.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.10.cfg -- infomation grepped

方法与你的方法相同,我刚刚添加了sed !!

答案 1 :(得分:1)

您需要先排序filename,然后将filename号码指定为打破平局

sort -t'.' -k1,4 -k5n,5n filename.txt
/full/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.3.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.12.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.20.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.2.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.18.cfg -- infomation grepped
/real/path/software/version1.2.3.4/filename.4.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.5.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.10.cfg -- infomation grepped

答案 2 :(得分:1)

我会创建一个排序键,然后对该排序键进行排序,然后删除排序键

让我们看看......

$ while read line
do
    dirname=${line%/*}   #Directory names
    number=$(echo "$line" | sed 's/.*\.\([0-9]*\)\.cfg.*/\1/')  # File number
    printf "%-60.60s %04d | %s\n" "$dirname" "$number" "$line"
done < filetext.txt | sort | sed "s/.* \| //"

这是从filetext.txt读取每一行并将其输入while read line循环。

dirname正在使用BASH中的${parameter%word}功能。这将取${parameter}的值并从右侧移除与模式word匹配的最小量。因此,${line%/*}正在使用$line,并且正在删除最后一个正斜杠和之后的所有字符。

number有点棘手。我注意到你在文件名末尾有.44.cfg之类的东西。这意味着如果我能找到那个特定的模式,我就能找到文件号。我的sed命令查找一个句点,后跟零个或多个数字,后跟.cfg。,并将这些数字标记为分组。然后我用第一个分组替换整行,给我一个数字。

接下来,我使用printf打印出目录和号码。我将目录名称空间填充为60个字符(如果需要可以增加),然后是四位数字。这会创建一个如下所示的排序键:

/full/path/software/version1.2.3.4                           0001
/full/path/software/version1.2.3.4                           0003
/full/path/software/version1.2.3.4                           0012
/full/path/software/version1.2.3.4                           0020
/long/path/software/version1.2.3.4                           0001
/long/path/software/version1.2.3.4                           0002
/long/path/software/version1.2.3.4                           0018
/real/path/software/version1.2.3.4                           0004
/total/path/software/version1.2.3.4                          0005
/total/path/software/version1.2.3.4                          0010

我将该行附加到此排序键,然后进行排序。之后,我从行中删除排序键。结果:

/full/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.3.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.12.cfg -- infomation grepped
/full/path/software/version1.2.3.4/filename.20.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.1.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.2.cfg -- infomation grepped
/long/path/software/version1.2.3.4/filename.18.cfg -- infomation grepped
/real/path/software/version1.2.3.4/filename.4.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.5.cfg -- infomation grepped
/total/path/software/version1.2.3.4/filename.10.cfg -- infomation grepped

注意我不会像其他人在答案中那样依赖文件名的特定格式。如果你有这样一条线怎么办?

/total/path/software/version1.2/filename.10.cfg -- infomation grepped

该行中没有五位小数。任何试图通过打破期间的字段进行排序的东西都将失败。以上仍然有效。