我有一个文件,其中包含如下记录:
434419\Teclu\Tudor\1501\9502
187650\Cosma\Sorin\1504\9253
239474\Teclu\Daniel\1502\5245
844936\Gaman\Mihai\1505\4074
942341\Avram\Tudor\1505\4543
137158\Gaman\Marius\1505\5244
531747\Francu\Daniel\1503\2226
382144\Teclu\Daniel\1501\9943
913409\Gaman\Mihai\1501\5473
901028\Avram\Mihai\1502\6169
382207\Dedu\Alex\1504\5428
726697\Gaman\Sorin\1502\5071
271503\Gaman\Ionut\1505\6643
147791\Dedu\Dragos\1503\4955
495572\Cosma\Alex\1505\9750
769482\Popescu\Sorin\1505\5472
410724\Marin\Mihai\1502\7317
381000\Marin\Daniel\1503\7321
251934\Popescu\Ionut\1504\8288
416161\Gaman\Mihai\1501\8245
523401\Gaman\Mihai\1504\3101
347491\Avram\Daniel\1504\2017
329372\Dedu\Sorin\1502\8528
509554\Popescu\Ionut\1502\7972
由 \ 分隔的字段。第一个字段是 ID,第二个字段是姓氏,第三个字段是名字,第四个字段是工资,第五个字段是绩效分数。
我必须编写一个脚本,该脚本接受一个参数(即姓氏),并在文件的第一行和最后 10 行中找到具有该名称的人。然后从这些人中提取工资最低的人,或者如果有两个或更多同名同工资的人,比较他们的绩效分数,并取分数较大的人。对于这个人,我必须打印身份证。
我尝试了头尾切割和更多命令的组合:
{ head -n 10 file.txt ; tail -n 10 file.txt } | grep $NAME | sort -t '\' -r k 4
按工资从最低到最高排序,但如果工资相同,我不知道下一步该怎么做。
答案1
保留命令的开头:
{ head -n 10 file.txt ; tail -n 10 file.txt; } |
grep $NAME | sort -t '\' -k 4 -k 5 |
awk -F'\\' '!wage{wage=$4;id=$1;next} wage==$4{id=$1} END{print id}'
这awk
脚本基本上将您给出的算法文本描述放入公式中。
当然,您也可以用更多 awk 逻辑替换管道中的前 3 个命令,例如:
$ myFun() {
awk -F'\\' -v s=$2 -v l=`wc -l<$1` '
$2==s&&(NR<11||NR>l-11)&&(!wage||wage>$4||(wage==$4&&$5>perf)){
wage=$4; id=$1; perf=$5;
}
END{ print id; }' $1; }
$ myFun exampleData.dsv Teclu
382144
$ myFun exampleData.dsv Gaman
416161
请注意注释中的 OP:awk 中的 '$1'、'$2' 等变量独立于同名的外壳变量。
答案2
TXR 口齿不清:
(defstruct person ()
id last first wage score
(:method equal (me)
(list (- me.wage) me.score)))
(let* ((surname (pop *args*))
(database (build (awk (:set fs "\\") ;; backslash field sep
((fconv i - - i i) ;; int, noconv, noconv, int, int
(add (new person
id [f 0] last [f 1] first [f 2]
wage [f 3] score [f 4])))))))
(del [database 10..-10]) ;; drop all but first/last ten
(let* ((select-surname (keep-if (op equal @1.last surname) database))
(best (find-max select-surname)))
(put-line (if best `best ID: @{best.id}` "notfound"))))
测试:
$ txr process.tl nonexistent data
notfound
$ txr process.tl Teclu data
best ID: 382144
$ txr process.tl Gaman data
best ID: 416161
$ txr process.tl Popescu data
best ID: 509554
$ txr process.tl Francu data
best ID: 531747
(find-max select-surname)
为什么我们可以使用一个简单的方法(即将find-max
函数应用于按姓氏过滤的数据库)来找到最佳 ID,这里的技巧是平等替代 为结构体定义的方法person
:
(:method equal (me)
(list (- me.wage) me.score))
equal
当此方法存在时,每当使用或less
更大的值比较此类型的对象,或在:equal-based
哈希表等中进行哈希处理时,equal
都会调用该对象的方法并使用返回值代替其位置。因此,我们在这里所说的是,person
使用由否定工资(因此越低越好)和分数组成的列表来比较两个对象的相等性。从那里开始,列表相等/不等的常规 TXR Lisp 语义适用:
1> (greater '(1 1) '(1 0))
t
2> (greater '(1 1) '(1 2))
nil
3> (greater '(2 1) '(1 2))
t
比较相应的第一个元素,如果它们相等,则比较第二个元素,依此类推。