Сортировка пар строк по одному полю в одной из этих строк
Я пытаюсь преобразовать поток как:
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
В:
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
... сортируя по второму разделенному запятыми полю строк, начинающихся с #
, переупорядочивая другие строки рядом с теми, что с ключами сортировки.
Поэтому я выполняю сортировку только по строкам, содержащим "#EXTINF", и сортирую после ",". Следует также сохранить строку ниже (строка URL) отсортированной строки с ним.
3 ответа
Вот один, использующий GNU awk's asort
:
$ awk '
BEGIN { FS="," } # define , as field separator
{
p=( NR%2 ? $2 : p ) # every other record updates p
a[p]=a[p] (a[p]==""?"":ORS) $0 # second record in pair is appended to
} # first ORS separated
END {
n=asort(a,b,"@ind_str_asc") # sort on key
for(i=1;i<=n;i++) # loop them
print b[i] # and output
}' file
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
Он поддерживает только уникальные ключи в$2
Является ли группа записей с равными $2
но не заказывает в этой группе, например:
$ awk '{...}' file file
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
Преобразуйте ваши данные в легко сортируемый формат, а затем сортируйте их обратно. Так:
to_one_line_per_record() {
local inf_line= line=
while read -r line; do
if [[ $line = "#"* ]]; then
inf_line=$line
else
printf '%s\n' "${inf_line},$line"
fi
done
}
from_one_line_per_record() {
local inf_f1 inf_f2 url
while IFS=, read -r inf_f1 inf_f2 url; do
printf '%s,%s\n%s\n' "$inf_f1" "$inf_f2" "$url"
done
}
to_one_line_from_record | sort -t, -k2,2 | from_one_line_per_record
С вашим данным входом, выход to_one_line_per_record
является:
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC,http://AnotherStreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD,http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery,http://DisStreamUrl.m3u8
Проходя через это sort -t, -k2,2
, вывод становится:
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD,http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery,http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC,http://AnotherStreamUrl.m3u8
И передавая это через from_one_line_per_record
, это превращается в:
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
По структуре похож на ответ от @Charles, но использует маленький awk
скрипты вместо функций bash.
Сохраните следующее в своем собственном файле с именем (например) sortem.sh:
#!/usr/bin/env bash
set -e
[[ $# -ge 1 ]] && exec < "$1"
awk -F , '/^#EXTINF/ {s=$0} /^http/ {print s FS $0}' | \
sort -t , -k 2,2 | \
awk -F , '{print $1 FS $2 "\n" $3}'
Сделайте файл исполняемым через:
$ chmod +x sortem.sh
Определите файл, в котором сохраняются входные данные для обработки. Например, вы можете сохранить его в файле с именем sortem_input.txt
, С помощью cat
для отображения содержимого этого файла показывает:
$ cat sortem_input.txt
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
Обработайте этот ввод, используя такой вызов:
$ ./sortem.sh sortem_input.txt
...или же:
$ ./sortem.sh < sortem_input.txt
... или вообще:
$ <commands that generate input> | ./sortem.sh
Вывод выглядит так:
#EXTINF:-1 tvg-logo="http://randomUrl.com/icon.png",ABC HD
http://StreamUrl.m3u8
#EXTINF:-1 tvg-logo="http://YetAnotherRandomUrl.com/icon.png",Discovery
http://DisStreamUrl.m3u8
#EXTINF:-1 group-title="SERVER 1-Tv" tvg-logo="http://anotherRandomUrl.com/icon.png",NBC
http://AnotherStreamUrl.m3u8