Сортировка нескольких таблиц внутри файла Markdown с разбросанным между ними текстом - PullRequest
0 голосов
/ 11 октября 2019

Существует файл Markdown с заголовками, текстом и несортированными таблицами. Я хочу программно отсортировать каждую таблицу по ID, который является 3-м столбцом, в порядке убывания, предпочтительно с помощью PowerShell или Bash. Таблица останется на своем месте в файле.

# Heading

Text

| Col A   | Col B   | ID |
|---------|---------|----|
| Item 1A | Item 1B | 8  |
| Item 2A | Item 2B | 9  |
| Item 3A | Item 3B | 6  |

# Heading

Text

| Col A   | Col B   | ID |
|---------|---------|----|
| Item 4A | Item 4B | 3  |
| Item 5A | Item 5B | 2  |
| Item 6A | Item 6B | 4  |

Я не могу контролировать, как создается файл Markdown. Верно.

В идеале файл должен оставаться в Markdown после сортировки для дополнительной обработки. Однако я безуспешно исследовал эти варианты:

  • Преобразование в JSON и сортировка (решения, которые я пробовал, не согласуются с таблицами)
  • Преобразование в HTML и сортировка (только найденный JavaScriptрешения)
  • Этот скрипт сам по себе, хотя и полезен, должен быть изменен для анализа файла Markdown (возникли проблемы с нахождением понятного руководства о том, как запустить скрипт для содержимого между двумя строками)

Причина командной строки (а не JavaScript в HTML, например) заключается в том, что это преобразование будет происходить в конвейере выпуска Azure. Можно добавить функцию Azure в конвейер, что позволило бы мне запускать код JavaScript в облаке, и я буду продолжать это, если ничего не получится. Сначала я хочу исчерпать параметры командной строки, потому что я не очень хорошо знаком с JavaScript или с тем, как передавать контент между функциями и выпусками.

Спасибо за любые идеи.

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Изменяя указанный скрипт, как насчет:

flush() {
    printf "%s\n" "${lines[@]:0:2}"
    printf "%s\n" "${lines[@]:2}" | sort -t \| -nr -k 4
    lines=()
}

while IFS= read -r line; do
    if [[ ${line:0:1} = "|" ]]; then
        lines+=("$line")
    else
        (( ${#lines[@]} > 0 )) && flush
        echo "$line"
    fi
done < input.md
(( ${#lines[@]} > 0 )) && flush

Вывод:

# Heading

Text

| Col A   | Col B   | ID |
|---------|---------|----|
| Item 2A | Item 2B | 9  |
| Item 1A | Item 1B | 8  |
| Item 3A | Item 3B | 6  |

# Heading

Text

| Col A   | Col B   | ID |
|---------|---------|----|
| Item 6A | Item 6B | 4  |
| Item 4A | Item 4B | 3  |
| Item 5A | Item 5B | 2  |

Кстати, если Perl является вашим вариантом, вот альтернатива:

perl -ne '
    sub flush {
        print splice(@ary, 0, 2);   # print header lines
        # sort the table with keying the ID by Schwartzian transform
        print map { $_->[0] }
            sort { $b->[1] <=> $a->[1] }
            map { [$_, (split(/\s*\|\s*/))[3] ] }
            @ary;
        @ary = ();
    }

    # main loop
    if (/^\|/) {    # table section
        push(@ary, $_);
    } else {        # other section
        if ($#ary > 0) {
            &flush;
        } else {
            print;
        }
    }
    END {
        if ($#ary > 0) { &flush; }
    }
' input.md

Надеюсь, это поможет.

1 голос
/ 11 октября 2019

Если возможно определить таблицы уценки, небольшой 'awk' (или bash / python / perl) может фильтровать вывод. Предполагается, что каждая таблица имеет 2 строки заголовка.

awk -v 'FS="|" '
function cmp_id(i1, v1, i2, v2) {
    return v1-v2 ;
}

function show () {
    asorti(k, d, "cmp_id")
#    for (i=1 ; i<=n; i++ ) print i, k[i], d[i] ;
    # Print first 2 original header row, followed by sorted data lines
    print s[1] ; print s[2]
    for (i=1 ; i<=n; i++ ) if ( d[i]>=3 ) print s[d[i]] ;
    n = 0
}

    # Capture tables
/^\|/ { s[++n] = $0 ; k[n] = $4 ; next }
n > 0 { show() ; }
{ print }
END { show() ; }
'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...