Вставка опций команды из файла в команду

С недавней оболочкой (например. bash), попробуйте

mapfile -t TMP <file
TMP=(${TMP[@]/%/:1})
echo ${TMP[@]/#/-o }
-o line1:1 -o line2:1 -o line3:1
1
08.01.2021, 20:03
2 ответа

Как насчет этой функции?

hg_fold() {
    local -a config
    mapfile -t config < <(hg debugconfig)

    local -a opts
    for i in "$@"; do
        opts+=( --config "${config[i-1]}" )
    done
    opts+=(
        --exact  
        -r  2024:8679fc70eae8  
        -r  2021:8b3257871eac 
        -m "Fold"
    )

    echo HGRCPATH=/dev/null hg fold "${opts[@]}"
}

hg_fold 1 3 5

Удалите echo, если все в порядке.


Если вы хотите что-то более интерактивное, возможно,

hg_fold() {
    local -a opts
    select_options opts

    opts+=(
        --exact  
        -r  2024:8679fc70eae8  
        -r  2021:8b3257871eac 
        -m "Fold"
    )

    echo HGRCPATH=/dev/null hg fold "${opts[@]}"
}

select_options() {
    local -n options=$1
    local -a config
    mapfile -t config < <(hg debugconfig)

    local selecting=true
    PS3="Select a debugconfig item: "

    while $selecting; do
        select item in "${config[@]}" Done; do
            if [[ $item == "Done" ]]; then
                selecting=false
                break
            elif [[ -n $item ]]; then
                options+=( --config "$item" )
                config[REPLY-1]="*$item"  # mark it as selected
                break
            fi
        done
    done
}

hg_fold
1
18.03.2021, 22:37

I want to do a binary search on all the extensions that I have loaded to isolate the problem one.

Вот решение, которое подходит к этой проблеме с точки зрения разделяй и властвуй. Основная идея состоит в том, чтобы немного подготовить входной файл, а затем рекурсивно разделить его пополам; каждая половина выводится как пример команды, а затем рекурсивно обрабатывается на этих половинах. Вы должны выбрать, какую из примеров команд запустить, основываясь на визуальном осмотре, необходимом для определения успеха или неудачи команды. Вам нужно всего лишь выполнить четыре команды, чтобы найти виновника.

Вот простая -демонстрация процесса, чтобы лучше понять, что происходит. Скрипт выполняет рекурсию по 23 строкам и печатает каждую строку в этом формате:

$key = sed -n $start, $end p file

Вывод:

11 = sed -n 1,12p file
12 = sed -n 13,23p file
111 = sed -n 1,6p file
112 = sed -n 7,12p file
1111 = sed -n 1,3p file
1112 = sed -n 4,6p file
11111 = sed -n 1,2p file
11112 = sed -n 3,3p file
11121 = sed -n 4,5p file
11122 = sed -n 6,6p file
1121 = sed -n 7,9p file
1122 = sed -n 10,12p file
11211 = sed -n 7,8p file
11212 = sed -n 9,9p file
11221 = sed -n 10,11p file
11222 = sed -n 12,12p file
121 = sed -n 13,18p file
122 = sed -n 19,23p file
1211 = sed -n 13,15p file
1212 = sed -n 16,18p file
12111 = sed -n 13,14p file
12112 = sed -n 15,15p file
12121 = sed -n 16,17p file
12122 = sed -n 18,18p file
1221 = sed -n 19,21p file
1222 = sed -n 22,23p file
12211 = sed -n 19,20p file
12212 = sed -n 21,21p file

Каждая рекурсия имеет суффикс «1» или «2» из предыдущего запуска. Следуйте за «11» как за первым делением 1..23 на строки 1..12. Оттуда он делится на «111» и «112», которые представляют собой разделение на строки 1..6 и строки 7..12 соответственно. Если команда «11» выполнена успешно ,вы бы пропустили все последующие строки с префиксом "11.." -. Если команда «11» не удалась , вы сосредоточитесь на только на последующих строках с префиксом «11..» -. Промойте и повторите на каждой подразделенной группе линий.

В приведенном ниже сценарии используется тот же базовый алгоритм, но выходные данные преобразуются в фактические команды и sedвыходные данные.

#!/bin/sh

# prepare the file a bit
file=./extensions-file
sed 's/^/ --config /' "$file" > "$file".prepared

# specifically a () subshell instead of {} grouping, to insulate "N" variable changes
divide() (
  # args = prefix, start, end, suffix
  # output: recursive breakout of:
  #   $prefix $(sed start.. N) $suffix
  #   $prefix $(sed N+1.. end) $suffix
  # N = (end-start)/2

  n=$(( $2 + ($3-$2)/2 ))
  printf '%s %s %s\n' "${1}" "$(sed -n $2,${n}p "$file".prepared | tr -d '\n')"       "$4"
  printf '%s %s %s\n' "${1}" "$(sed -n $((n+1)),${3}p "$file".prepared | tr -d '\n')" "$4"
  if [ $((n - $2)) -gt 1 ]
  then
    divide "${1}" "$2" "$n" "$4"
  fi
  if [ $(( $3 - (n+1) )) -gt 1 ]
  then
    divide "${1}" "$((n+1))" "$3" "$4"
  fi
)

divide  "HGRCPATH=/dev/null hg fold"    \
        1                               \
        "$(wc -l < "$file".prepared)"   \
        "--exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m \"Fold\""

rm "$file".prepared

Сценарий немного подготавливает выходной файл расширений, добавляя перед каждой строкой пробел и текст « --config », чтобы нам не приходилось манипулировать им каждый раз, когда мы его распечатываем. Временный файл удаляется в конце.

Функция деления ()определяется и затем вызывается. Функция разделения ()сначала вычисляет (нижний предел )средней точки входящего диапазона. Затем он печатает примеры команд, основанные на использовании строк (start )... (n )и (n+1 ).. (end ). Три аргумента printf— это префикс, результат sedи суффикс. Мы определили префикс и суффикс в начальном вызове для разделения ()--, это просто текст, который находится по обе стороны от битов расширения. Команда sedпечатает запрошенные строки из файла, а затем передает их через trдля удаления новых строк, чтобы сделать вывод одной строкой. Здесь подготовка немного помогла --наличие префикса пробела в каждой строке означает, что мы можем довольно просто соединить строки.

Чтобы упростить отслеживание, вы можете отфильтровать выходные данные вышеприведенного скрипта через nl, чтобы присвоить идентификатор каждой строке. Отслеживайте эти идентификаторы по выходным данным приведенного ниже скрипта, которые также передаются через nl.

Следующий сценарий — это тот, который создал первоначальный «базовый» вывод выше.

#!/bin/sh
# specifically a () subshell instead of {} grouping, to insulate "N" variable changes
divide() (
  # args = prefix, start, end
  # output: recursive breakout of:
  #   "$prefix"1 = start.. N
  #   "$prefix"2 = N+1.. end
  # N = (end-start)/2

  n=$(( $2 + ($3-$2)/2 ))
  printf '%s = sed -n %d,%dp file\n' "${1}1" "$2" "$n"
  printf '%s = sed -n %d,%dp file\n' "${1}2" "$((n+1))" "$3"
  if [ $((n - $2)) -gt 1 ]
  then
    divide "${1}1" "$2" "$n"
  fi
  if [ $(( $3 - (n+1) )) -gt 1 ]
  then
    divide "${1}2" "$((n+1))" "$3"
  fi
)

divide 1 1 23

Для полноты картины вот вывод финального скрипта. Обратите внимание --некоторые строки очень длинные!

HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.convert= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.mq= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.schemes= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.progress= --config extensions.hgext.histedit= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.share= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"

Чтобы использовать вывод для поиска проблемного расширения, пронумеруйте предыдущий вывод (, возможно, передав его черезnl). Теперь у нас есть список из 28 команд. Команда «Выполнить» #1. Следуйте этим инструкциям:

для следующего шага.
  • Если #1 выполняется успешно, введите команду #17. Если #1 не удается выполнить, выполните команду #3.
  • Если #3 выполняется успешно, введите команду #11. Если #3 не удается выполнить, выполните команду #5.
  • Если #5 выполняется успешно, введите команду #9. Если #5 не удается выполнить, введите команду #7.
  • Если #7 выполняется успешно, проблема связана с расширением 3. Если #7 не выполняется, проблема связана с расширением 1 или 2.
  • Если #9 выполняется успешно, проблема связана с расширением 6. Если #9 не выполняется, проблема связана с расширением 4 или 5.
  • Если #11 выполняется успешно, введите команду #15. Если #11 не удается выполнить, введите команду #13.
  • Если #13 выполняется успешно, проблема связана с расширением 9. Если #13 не выполняется, проблема связана с расширением 7 или 8.
  • Если #15 выполняется успешно, проблема связана с расширением 12. Если #15 не выполняется, проблема связана с расширением 10 или 11.
  • Если #17 выполняется успешно, введите команду #25. Если #17 не удается выполнить, введите команду #19.
  • Если #19 выполняется успешно, введите команду #21. Если #19 не удается выполнить, введите команду #23.
  • Если #21 выполняется успешно, проблема связана с расширением 15. Если #21 не выполняется, проблема связана с расширением 13 или 14.
  • Если #23 выполняется успешно, проблема связана с расширением 18. Если #23 не выполняется, проблема связана с расширением 16 или 17.
  • Если #25 выполняется успешно, проблема связана с расширением 22 или 23. Если #25 не выполняется, выполните команду #27.
  • Если #27 выполняется успешно, проблема связана с расширением 21. Если #27 не выполняется, проблема связана с расширением 19 или 20.

Проблемные расширения идентифицируются по номеру строки в выходном файле hg debugconfig.

1
18.03.2021, 22:37

Теги

Похожие вопросы