我想对由日期组成的行进行排序,但是我无法弄清楚如何对行进行排序并保持整行。我也不明白如何使用管道对线进行排序。
例如,我的脚本将其作为文本文件接收:
asdsa 24 asdsa 3 3000 054217542 30.3.2016
asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
dsasda 23 dsada 4 3200 537358234 6.3.2016
我想逐行阅读:
while read line; do
done < "$1"
并按照日期对内线进行排序。我如何将这些行排序为文件中的行,而我逐一阅读它们?
如果我这样做怎么办:
#!/bin/bash
PATH=${PATH[*]}:.
#filename: testScript
while read line; do
arr=( $line )
num_of_params=`echo ${#arr[*]}`
echo $line | sort -n -k$num_of_params
num_of_params=0
done < "$1"
我的问题是我实际上是通过它自己发送的每一行来排序,而不是所有的行,但我不知道其他任何方式(不使用临时文件,我不是希望使用其中任何一种)。
输出:
asdsa 24 asdsa 3 3000 054217542 30.3.2016
asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
dsasda 23 dsada 4 3200 537358234 6.3.2016
期望的输出:
asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
dsasda 23 dsada 4 3200 537358234 6.3.2016
asdsa 24 asdsa 3 3000 054217542 30.3.2016
如你所见,它没有用。
我该如何解决?
答案 0 :(得分:1)
以下是使用Schwartzian transform与awk和cut
:
awk '{split($NF,arr,"."); printf("%d%02d%02d\t%s\n",arr[3],arr[2],arr[1],$0)}' infile |
sort -k 1,1 | cut -f 2-
awk部分首先将记录的最后一个字段$NF
(日期)分割为数组arr
:
split($NF,arr,".")
第二部分打印前面重新格式化日期的行:首先是年份,然后是月份和日期,后两个是零填充到两位数:
printf("%d%02d%02d\t%s\n",arr[3],arr[2],arr[1],$0)
输出结果如下:
20160330 asdsa 24 asdsa 3 3000 054217542 30.3.2016
20140102 asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
20160306 dsasda 23 dsada 4 3200 537358234 6.3.2016
现在我们可以直接转到sort
并使用第一个字段:
sort -k 1,1
导致
20140102 asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
20160306 dsasda 23 dsada 4 3200 537358234 6.3.2016
20160330 asdsa 24 asdsa 3 3000 054217542 30.3.2016
最后,我们再次使用cut
删除插入的字段,只留下第二个字段中的所有内容:
cut -f 2-
导致
asdsadsa 25 asdsadsaa 5 4500 534215365 2.1.2014
dsasda 23 dsada 4 3200 537358234 6.3.2016
asdsa 24 asdsa 3 3000 054217542 30.3.2016
如果我们只想使用Bash而不是awk,我们可以这样做:
#!/bin/bash
# Read each line into an array 'line'
while read -r -a line; do
# Find the number of array elements
nel=${#line[@]}
# Assign the last element of the array to 'date'
date=${line[nel-1]}
# Extract the month from the date with parameter expansion
month=${date#*.}
month=${month%.*}
# Year and day need only one expansion step, which is done here directly
printf "%d%02d%02d\t%s\n" "${date##*.}" "$month" "${date%%.*}" "${line[*]}"
# Pipe result to sort, then remove the first column with cut
done < infile | sort -k 1,1 | cut -f 2-
总体思路完全相同:我们添加一个包含重新格式化日期的额外列,按类别排序,然后再将其删除。
答案 1 :(得分:1)
尝试
awk -F"[\. ]*" '
{
printf "%d%02d%02d %s\n", $NF, $(NF-1), $(NF-2), $0
}' test | sort -n | cut -c10-
test
当然是您文件的名称...这取决于您在初始帖子中指定的格式中每行的最后一部分的日期。 (使用(n)awk在FreeBSD上测试)