Объединение файлов по значениям таблицы

Совсем недавно я сам боролся с этой странной проблемой тени блока курсора на новом (для меня )ноутбуке Dell XPS, на который я устанавливал Fedora 30 (, хотя эта проблема явно не специфична для Fedora -. ] множество отчетов об Ubuntu и некоторых других ). В ноутбуке есть как NVidia GeForce GTX 1050, так и контроллер Intel 915.

Теперь я считаю, что проблема напрямую связана с тем фактом, что есть ДВА видеоконтроллера, которые, возможно, каким-то образом борются друг с другом. BIOS на этом конкретном ноутбуке не контролирует видеоконтроллеры, поэтому я не могу просто отключить Intel.

Кроме того, в этой системе драйвер nouveau полностью зависает (X-сервер запускается и жестко блокируется -хотя, оглядываясь назад, возможно, это та же проблема ). В любом случае, "переключиться на новый драйвер" просто не было возможности из-за жесткого зависания!

Итак, после целого дня экспериментов с драйверами Nvidia (установка, удаление, сборка из Nvidia direct, удаление, переустановка из RPM Fusion и т.д. и т.п. -Тьфу! ), я наконец-то нашел волшебное заклинание, благодаря которому все заработало без надоедливого курсора!

Решение определенно не является интуитивным! И, как и во всех подобных вещах, YMMV (или, что более вероятно, «Ваш пробег будет меняться» )!

По сути, вам нужно управлять видеоконтроллером через параметры загрузки ядра.Вот что сработало:

(Во-первых, если вы используете драйвер nouveau -, УДАЧИ, и ПРЕКРАТИТЕ читать здесь)

1 )Убедитесь, что драйвер xorg -x11 -drv -nouveau отсутствует в вашей системе -удалите его.

2 )Убедитесь, что модуль ядра nouveau не будет загружаться, создав файл modprobe из черного списка (, даже если вы удалили X-драйвер, в ядре все еще есть модуль драйвера, поставляемый с ним ). Поместите следующие строки в файл с именем/etc/modprobe.d/blacklist-nouveau.conf:

blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off

3 )Затем убедитесь, что драйвер nouveau не проникнет во время загрузки, добавив следующее в параметры загрузки ядра:rd.driver.blacklist=nouveau modprobe.blacklist=nouveau. Если вы запускаете grub, то самое быстрое, что нужно сделать, это изменить /etc/default/grubи добавить эти параметры в переменную GRUB_CMDLINE_LINUXи повторно -запустить grub2 -mkconfig. Обратите внимание :, если вы устанавливаете драйверы nvidia RPM Fusion, он также добавит эти строки.

Хорошо, теперь, когда драйвер nouveau исправен и отключен, теперь вам просто нужно настроить выбор между драйвером i915 и драйверами nvidia...

Если вы еще этого не сделали, получите и установите драйверы Nvidia (как хотите -В итоге я использовал только драйверы RPM Fusion ).

После установки драйверов Nvidia вы могли заметить, что параметры загрузки ядра были изменены и теперь включают «nvidia -drm.modeset=1», что фактически говорит ядру использовать драйвер Nvidia для вывода видео -. смысл, да? ЭТО ПРОБЛЕМА .

--> На этом этапе измените эти параметры загрузки на nvidia-drm.modeset=0и добавьте i915.modeset=1.

Это кажется ОЧЕНЬ счетчиком -интуитивно понятным, поскольку вы хотите ИСПОЛЬЗОВАТЬ контроллер Nvidia. Однако то, что может происходить, является конфликтом при запуске X. Я случайно обнаружил эту конфигурацию, начиная удалять драйверы Nvidia в четвертый раз.Я перезагрузился с i915.modeset=1 и удалял драйверы, когда увидел, что X-сервер все еще работает с драйвером Nvidia, и мой курсор был в порядке. Затем я закончил удаление, перезагрузился обратно в Intel, затем снова установил и сломал его. Именно тогда я понял, что, возможно, режим ядра должен быть обратным.

В любом случае, как только вы загрузитесь в этой конфигурации, X-сервер запустится, и он должен автоматически обнаружить карту Nvidia и использовать ее. Если это не происходит автоматически, вам может потребоваться выполнить конфигурацию X11, которая настраивает контроллер Nvidia (, вы можете попробовать инструмент nvidia -xconfig, если вам нужно -, что я сделал в какой-то момент в этом вообще кошмар, но в итоге мне не понадобилась даже эта конфигурация ).

Чтобы закончить, возможно, запустите тест glmark2, чтобы убедиться, что ваша производительность выглядит правильно (он также покажет используемый графический процессор ).

7
20.10.2021, 13:44
2 ответа

Приведенный ниже сценарий предполагает, что все файлы, которые вы хотите объединить, соответствуют шаблону *.tsv. Если вы знаете, что все они соответствуют ABC*.tsv, вы можете использовать этот шаблон в начале скрипта вместо *.tsv.

Кроме того, в сценарии предполагается, что все имена файлов, входящие в определенную группу, генерируются как непрерывный подсписок -списка, до которого расширяется *.tsv.

#!/bin/sh

set -- *.tsv

while read -r group first last; do
        collect=false

        for name do
                if ! "$collect"; then
                        [ "$name" = "$first.tsv" ] || continue
                        collect=true
                fi

                if "$collect"; then
                        cat -- "$name"
                        [ "$name" = "$last.tsv" ] && break
                fi
        done >"$group.tsv"

done <info.tsv

Сценарий устанавливает список позиционных параметров в список имен, соответствующих *.tsv. Затем он считывает три поля каждой строки из info.tsvв переменные group, firstи last.

Для каждой строки, считанной из info.tsvтаким образом, список позиционных параметров сканируется на наличие имен, совпадающих с первым именем в группе. Как только это первое имя найдено, мы устанавливаем флаг collect, который указывает логике скрипта начать сбор данных из файлов, названных в списке позиционных параметров, с текущей позиции в списке. Это заканчивается, когда мы сталкиваемся с именем, которое соответствует фамилии группы.

Обратите внимание, что здесь trueи falseиспользуются как команды, а не простые строки. Значение, хранящееся в переменной $collect, выполняется в if ! "$collect", так что это означает, что скрипт выполнит одну из двух встроенных команд оболочки trueили false.В оболочке нет специальных ключевых слов для true или false, как в некоторых других языках (, например. Питон )делать.

Тестирование:

$ ls
script
$ touch ABC{1234001..1234030}.tsv
$ for name in ABC*.tsv; do printf 'Name: %s\n' "$name" >"$name"; done
$ cat ABC1234015.tsv
Name: ABC1234015.tsv
$ cat >info.tsv <<END_DATA
group1 ABC1234001 ABC1234010
group2 ABC1234025 ABC1234030
END_DATA
$./script
$ cat group1.tsv
Name: ABC1234001.tsv
Name: ABC1234002.tsv
Name: ABC1234003.tsv
Name: ABC1234004.tsv
Name: ABC1234005.tsv
Name: ABC1234006.tsv
Name: ABC1234007.tsv
Name: ABC1234008.tsv
Name: ABC1234009.tsv
Name: ABC1234010.tsv
$ cat group2.tsv
Name: ABC1234025.tsv
Name: ABC1234026.tsv
Name: ABC1234027.tsv
Name: ABC1234028.tsv
Name: ABC1234029.tsv
Name: ABC1234030.tsv

Как упоминалось в комментариях к этому ответу, я бы разработал этот скрипт для личного использования, оставив его таким:

#!/bin/sh

while read -r group first last; do
        collect=false

        for name do
                filename=$( basename "$name" )

                if ! "$collect"; then
                        [ "$filename" = "$first.tsv" ] || continue
                        collect=true
                fi

                if "$collect"; then
                        cat -- "$name"
                        [ "$filename" = "$last.tsv" ] && break
                fi
        done >"$group.tsv"

done

Обратите внимание на удаление команды setвверху (это будет заменено аргументами командной строки ), а удаление перенаправления изinfo.tsv(это будет заменено перенаправлением на команду строка ). Я также ввел переменную filename, которая будет содержать компонент имени файла из путей, заданных в командной строке.

Затем я запускал скрипт вот так:

$./script ABC*.tsv <info.tsv

С помощью этого я добился того, что сценарий не зависит от того, где хранится список входных групп или как он называется, и ему все равно, как ABCназываются файлы (, если они имеют .tsvсуффикс имени файла )или где они хранятся.

4
20.10.2021, 14:54

Ваш подход — хорошая идея, но, к сожалению, он не будет работать, потому что переменные не раскрываются внутри фигурных скобок:

$ echo {1..5}
1 2 3 4 5
$ a=1
$ b=5
$ echo {$a..$b}
{1..5}

Вы можете обойти это, используя eval, хотя:

sed 's/ABC//g' info.tsv | 
    while read -r group start end; do 
        files=( $(eval echo ABC{$start..$end}.tsv) )
        cat "${files[@]}" > "$group.tsv"; 
    done 

Это сначала удалит все экземпляры ABCиз файла info.tsv, чтобы мы могли получить только числа. Обратите внимание, что это предполагает точную структуру данных, которую вы нам показали. Если ABCтакже может присутствовать в имени группы, то это сломается.

После удаления ABCрезультат передается в цикл while, который считывает три переменные :$group, $startи $end. Затем они передаются в eval, который расширяет переменную перед вызовом раскрытия фигурной скобки, позволяя вам получить список имен файлов :

.
$ eval echo ABC{1..5}
ABC1 ABC2 ABC3 ABC4 ABC5

Результат evalсохраняется в массиве $files, который передается в качестве входных данных вcat:

cat "${files[@]}" > "$group.tsv";
2
20.10.2021, 14:54

Теги

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