как сортировать по дням недели?

У меня два файла.

file1:

Dave 734.838.9800 Bob 313.123.4567 Carol 248.344.5576 Mary 313.449.1390 Ted 248.496.2204 Alice 616.556.4458 

file2:

 Bob Tuesday Carol Monday Ted Sunday Alice Wednesday Dave Thursday Mary Saturday 

Я объединил два файла.

file3 должен выглядеть следующим образом:

 Name On-Call Phone Carol MONDAY 248.344.5576 Bob TUESDAY 313.123.4567 Alice WEDNESDAY 616.556.4458 Dave THURSDAY 734.838.9800 Nobody FRIDAY 634.296.3356 Mary SATURDAY 313.449.1390 Ted SUNDAY 248.496.2204 

Но я не могу заставить будни быть в порядке. Как мне это сделать?

Вот еще один способ сделать это (короткая версия, без временных файлов):

 { printf %s\\n "Name On-Call Phone"; join -a1 -j2 -o 1.1 2.1 1.2 2.3 -e "Nobody" \ <(printf %s\\n '5 Friday' '1 Monday' '6 Saturday' '7 Sunday' '4 Thursday' '2 Tuesday' '3 Wednesday') \ <(join <(sort file2) <(sort file1) | sort -k2) | sort -k2n | sort -k1n | \ cut -d' ' -f 2-; } | column -t 

Если вам абсолютно нужны имена дней в шапках, тогда:

 { printf %s\\n "Name On-Call Phone"; join -a1 -j2 -o 1.1 2.1 1.3 2.3 -e "Nobody" <(cat <<IN 5 Friday FRIDAY 1 Monday MONDAY 6 Saturday SATURDAY 7 Sunday SUNDAY 4 Thursday THURSDAY 2 Tuesday TUESDAY 3 Wednesday WEDNESDAY IN ) <(join <(sort file2) <(sort file1) | sort -k2) | sort -k2n | sort -k1n | cut -d' ' -f 2-; } | column -t 

Длинная версия:
Допустим, у нас есть два файла: file1 :

 Dave 734.838.9800 Bob 313.123.4567 Carol 248.344.5576 Mary 313.449.1390 Ted 248.496.2204 Alice 616.556.4458 Jimmy 324.555.8867 Harry 422.858.2354 Lou 788.907.6859 

и file2 :

 Bob Tuesday Carol Monday Jimmy Wednesday Ted Sunday Alice Wednesday Dave Thursday Harry Monday Mary Saturday Lou Sunday 

Мы создаем file3 со следующим содержимым:

 1 Monday MONDAY 2 Tuesday TUESDAY 3 Wednesday WEDNESDAY 4 Thursday THURSDAY 5 Friday FRIDAY 6 Saturday SATURDAY 7 Sunday SUNDAY 

а затем запустить:

 { printf %s\\n "Name On-Call Phone"; \ join <(sort file2) <(sort file1) | sort -k2 | \ join -a1 -j2 -o 1.1 2.1 1.3 2.3 -e "Nobody" <(sort -k2 file3) - \ | sort -k1n | cut -d' ' -f 2-; } | column -t 

или, в одной строке:

 { printf %s\\n "Name On-Call Phone"; join <(sort file2) <(sort file1) | sort -k2 | join -a1 -j2 -o 1.1 2.1 1.3 2.3 -e "Nobody" <(sort -k2 file3) - | sort -k1n | cut -d' ' -f 2-; } | column -t 

Вывод:

 Name On-Call Phone Carol MONDAY 248.344.5576 Harry MONDAY 422.858.2354 Bob TUESDAY 313.123.4567 Alice WEDNESDAY 616.556.4458 Jimmy WEDNESDAY 324.555.8867 Dave THURSDAY 734.838.9800 Nobody FRIDAY Nobody Mary SATURDAY 313.449.1390 Lou SUNDAY 788.907.6859 Ted SUNDAY 248.496.2204 

Как это работает:
join <(sort file2) <(sort file1) | sort -k2 join <(sort file2) <(sort file1) | sort -k2 – первые два файла объединяются на основе второго поля, тогда результат сортируется по второму столбцу:

 Carol Monday 248.344.5576 Harry Monday 422.858.2354 Mary Saturday 313.449.1390 Ted Sunday 248.496.2204 Lou Sunday 788.907.6859 Dave Thursday 734.838.9800 Bob Tuesday 313.123.4567 Jimmy Wednesday 324.555.8867 Alice Wednesday 616.556.4458 

это соединение по join -a1 -j2 -o 1.1 2.1 1.3 2.3 -e "Nobody" <(sort -k2 file3) - для join -a1 -j2 -o 1.1 2.1 1.3 2.3 -e "Nobody" <(sort -k2 file3) - присоединиться к нему с file3 на основе второго поля; -a1 добавляет непревзойденные строки из файла3 в вывод и -e "Nobody" заменяет отсутствующие выходные поля "Nobody" :

 5 Nobody FRIDAY Nobody 1 Carol MONDAY 248.344.5576 1 Harry MONDAY 422.858.2354 6 Mary SATURDAY 313.449.1390 7 Ted SUNDAY 248.496.2204 7 Lou SUNDAY 788.907.6859 4 Dave THURSDAY 734.838.9800 2 Bob TUESDAY 313.123.4567 3 Jimmy WEDNESDAY 324.555.8867 3 Alice WEDNESDAY 616.556.4458 

результат снова будет sort -k1n | cut -d' ' -f 2- для sort -k1n | cut -d' ' -f 2- sort -k1n | cut -d' ' -f 2- для численного сортировки вывода на 1-ом поле, а затем удалить 1-е поле:

 Carol MONDAY 248.344.5576 Harry MONDAY 422.858.2354 Bob TUESDAY 313.123.4567 Alice WEDNESDAY 616.556.4458 Jimmy WEDNESDAY 324.555.8867 Dave THURSDAY 734.838.9800 Nobody FRIDAY Nobody Mary SATURDAY 313.449.1390 Lou SUNDAY 788.907.6859 Ted SUNDAY 248.496.2204 

так как это было сгруппировано {...} с printf %s\\n "Name On-Call Phone" который печатает заголовок, весь вывод затем передается в column -t чтобы префлотировать его.


Вы можете пропустить один sort если файл3 уже отсортирован по второму столбцу (например, на этот раз с простым двухстолбцовым файлом3):

 5 Friday 1 Monday 6 Saturday 7 Sunday 4 Thursday 2 Tuesday 3 Wednesday 

а также присвоить номер телефона "Nobody" например, sed 's/Nobody/888.000.8888/2' :

 { printf %s\\n "Name On-Call Phone"; join <(sort file2) <(sort file1) | \ sort -k2 | join -a1 -j2 -o 1.1 2.1 1.2 2.3 -e "Nobody" file3 - | sort -k1n | \ cut -d' ' -f 2-; } | sed 's/Nobody/888.000.8888/2' | column -t 

вывод:

 Name On-Call Phone Carol Monday 248.344.5576 Harry Monday 422.858.2354 Bob Tuesday 313.123.4567 Alice Wednesday 616.556.4458 Jimmy Wednesday 324.555.8867 Dave Thursday 734.838.9800 Nobody Friday 888.000.8888 Mary Saturday 313.449.1390 Lou Sunday 788.907.6859 Ted Sunday 248.496.2204 
 awk ' BEGIN { print "Name On-Call Phone" split("MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY", days); } NR == FNR { day[$1] = $2; next } { lines[toupper(day[$1])] = $1 OFS toupper(day[$1]) OFS $2 } END { for (i=1; i<=7; i++) { if (lines[days[i]]) print lines[days[i]] else print "Nobody", days[i] } } ' file2 file1 | column -t 
 Name On-Call Phone Carol MONDAY 248.344.5576 Bob TUESDAY 313.123.4567 Alice WEDNESDAY 616.556.4458 Dave THURSDAY 734.838.9800 Nobody FRIDAY Mary SATURDAY 313.449.1390 Ted SUNDAY 248.496.2204