Извлечь части имен файлов с помощью регулярного выражения в bash

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

ACC_svs_ECC.nii.gz
ACC_svs_noECC.nii.gz
ACC_svs_ref.nii.gz
Lt Hippocampus_svs_ECC.nii.gz
Lt Hippocampus_svs_noECC.nii.gz
Lt Hippocampus_svs_ref.nii.gz

Это буквально единственные возможности для имен файлов, а не шаблона или примера. все имена файлов. у каждого участника будут эти 6 файлов для двух сеансов, но имена файлов будут одинаковыми, пока я не изменю их на совместимые с BIDS. Файлы json являются дополнительными файлами, поэтому имя файла точно такое же, как у .nii.gz, за исключением файлов .json.

Каждое имя файла имеет область мозга (ACC или Lt Hippocampus) и тип файла mrs (ECC, noECC и ref). Это информация, которая мне понадобится в новых именах файлов, поэтому, просматривая каждое существующее имя файла, я хотел бы использовать их в новом имени файла.

Вот как будет выглядеть код:

#!/bin/bash

ID=$1 # participant ID= user input
ses=$2 # session no (MRI)= user input
bidsdir=path/path/sub-001/ses-MRI1/mrs/ # path to mrs folder as specified by BIDS

for file in "${bidsdir}"; do
   voi= # either ACC of Lt Hippocampus
   type= # either ECC, noECC, or ref
   ext= # file extension- either .nii.gz or .json
   newfilename = "sub-${ID}_ses-${ses}_voi-${voi}_acq-svs_${type}_mrs.${ext}"
   # rest of code to rename each file
   mv $bidsdir$file $bidsdir$newfilename
done

Я привык использовать регулярное выражение с Python, и у меня это неплохо получается, но у меня нет времени тратить еще час на то, чтобы разобраться с этим в bash. Вот как далеко я продвинулся с самим регулярным выражением: (?P<voi>ACC|Lt\ Hippocampus)_svs_(?P<type>ECC|noECC|ref)

обновите код, чтобы показать, где вы устанавливаете и ссылаетесь на регулярное выражение; также обновите код, чтобы показать, что вы назначаете переменным voi, type и ext.

markp-fuso 10.06.2024 17:42

все имена файлов имеют ровно два подчеркивания и две точки? если мы удалим все после точек, у нас останется строка с двумя разделителями подчеркивания... будет ли эта часть имени файла всегда иметь формат brain-region + _ + литеральная строка svs + _ + type?

markp-fuso 10.06.2024 17:46

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

markp-fuso 10.06.2024 17:48
[[ $file =~ (ACC|Lt Hippocampus)_svs_(ECC|noECC|ref).*(nii[.]gz|json)$ ]] && declare -p BASH_REMATCH
jhnc 10.06.2024 17:49

Bash использует синтаксис расширенных регулярных выражений POSIX. RE, который вы показали, но не используете, не соответствует этому синтаксису.

Shawn 10.06.2024 17:52

@markp-fuso Я не добавлял файлы .json для экономии места. Файлы .json являются дополнительными к .nii.gz, поэтому имена файлов точно такие же, за исключением расширения. Что касается вашего второго вопроса – да. Примеры, которые я привел, представляют собой все возможные варианты имен файлов.

Julia 10.06.2024 18:42

@Шон, я не знаю, что это значит. Обычно я использую regex101 для написания регулярного выражения, а затем нажимаю «python» слева. У меня нет другого опыта регулярных выражений, поэтому мой вопрос

Julia 10.06.2024 18:43

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

markp-fuso 10.06.2024 19:41

То, что сказал @Shawn, означает, что регулярное выражение, которое у вас есть в вашем вопросе (которое выглядит так, как будто это может быть регулярное выражение, несовместимое с POSIX Perl, то есть PCRE, возможно, с некоторыми python-измами, я не знаю), не является хорошей отправной точкой для написание регулярного выражения, понятного bash (т. е. POSIX-совместимого расширенного регулярного выражения, ERE).

Ed Morton 10.06.2024 19:44

Пожалуйста, отредактируйте свой вопрос, чтобы показать ожидаемый результат — ваши требования еще не ясны, а образец входных данных — это только половина того, что нам нужно, чтобы протестировать потенциальное решение.

Ed Morton 10.06.2024 19:49

@EdMorton более эффективно использовать itertools.product в Python, таким образом вы можете легко сгенерировать ожидаемый результат на основе информации в сообщении. рад поделиться кодом, если вы не знаете, как это сделать. Но это также указано в ответе ниже (хотя код не работает).

Julia 10.06.2024 23:50

рассмотрите возможность просмотреть минимальный воспроизводимый пример и затем соответствующим образом обновить вопрос; имейте в виду, что большинство людей, просматривающих этот вопрос, возможно, не знают, что такое файлы BIDS и sidecar, и в этом случае это не имеет значения, важно (очень) основное требование для анализа имени файла; если у вас есть время оставлять комментарии и предлагать python/itertools код для генерации желаемого результата, то его не составит труда запустить python/itertools в вашей системе и просто вырезать и вставить результат в вопрос

markp-fuso 11.06.2024 00:23

@markp-fuso Я думаю, что результат очевиден, исходя из моего вопроса (т. е. переменной newfilename), особенно учитывая комментарии, которые я предоставил рядом с переменными voi и type. Я также написал, какая часть кода не работает, в комментарии к этому ответу (обратите внимание, что мой комментарий был оставлен 5 часов назад, а ответ был отредактирован 4 часа назад).

Julia 11.06.2024 00:39

@Джулия, я думаю, ты ответил не тому человеку, поскольку твой комментарий кажется не имеющим отношения к моему.

Ed Morton 11.06.2024 03:42

Я не понимаю, где в вашем сценарии вы применяете регулярное выражение. Кроме того, многие детали (например, петля for) не имеют отношения к проблеме. Создайте простой воспроизводимый пример вашей проблемы, покажите свою попытку ее решения и объясните, где ваша попытка не удалась.

user1934428 11.06.2024 09:05

@user1934428 user1934428 Это потому, что я не применяю регулярное выражение, потому что не знаю как (именно поэтому и задаю этот вопрос). Как я могу создать более воспроизводимый пример, если я уже предоставил все, что умею делать. Если вы не знаете ответа после того, как я указал все, что знаю, или если вы понимаете вопрос, вы можете просто нажать на другой вопрос. Однако вы решили прокомментировать уже решенный вопрос, просто чтобы сказать мне, что мой вопрос глупый.

Julia 11.06.2024 13:49

Многие люди пытаются использовать оператор регулярного выражения bash, но делают это неправильно, поэтому вполне нормально иметь вопрос об этом, что свидетельствует о попытке сделать это. Оператор регулярного выражения внутри команды [[ ... ]] записывается как =~, и если вы просмотрите справочную страницу bash для этой строки, вы быстро найдете объяснение того, как его использовать, а также ссылку на язык регулярных выражений, поддерживаемый bash (который не такой мощный, как тот, который вы используете в Python). Кроме того, поиск в Google примеров регулярных выражений bash дает вам множество результатов, поэтому мы можем ожидать, что вы хотя бы попытаетесь это сделать.

user1934428 11.06.2024 16:22

См., например, страницу stackoverflow как задать вопрос и ответы к этому обсуждению, где подсказки, как улучшить ваш вопрос.

user1934428 11.06.2024 16:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
18
103
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Предположения:

  • формат имени файла всегда будет иметь 2 подчеркивания и одну или две точки
  • формат имени файла всегда будет иметь следующий формат: <brain-region> + _ + <some-string-to-ignore> + _ + <type> + { .nii.gz или .json }

Добавление записи .json в список имен файлов OP:

$ ls -1 /tmp/testd
ACC_svs_ECC.nii.gz
ACC_svs_noECC.nii.gz
ACC_svs_ref.nii.gz
'Lt Hippocampus_svs_ECC.nii.gz'
'Lt Hippocampus_svs_noECC.nii.gz'
'Lt Hippocampus_svs_ref.json'
'Lt Hippocampus_svs_ref.nii.gz'

В этом конкретном случае я бы пропустил хлопоты/сложности регулярного выражения и использовал комбинацию подстановки параметров (чтобы удалить путь) и встроенную функцию bash / read (в сочетании с двойными разделителями _ и .) для анализа файла. имена в нужные переменные:

ID='myid'
ses='myses'
bidsdir='/tmp/testd'

for path_file in "${bidsdir}"/*{.nii.gz,.json}
do
    oldfilename = "${path_file##*/}"                         # strip off the path (via parameter substitution)
    IFS='_.' read -r voi x type ext <<< "${oldfilename}"   # parse old file name into variables based on dual delimimters "_" and "."

    newfilename = "sub-${ID}_ses-${ses}_voi-${voi}_acq-svs_${type}_mrs.${ext}"

    echo "path/file = ${path_file}"
    echo "old file  = ${oldfilename}"
    echo "new file  = ${newfilename}"
    echo ""
done

Это генерирует:

path/file = /tmp/testd/ACC_svs_ECC.nii.gz
old file  = ACC_svs_ECC.nii.gz
new file  = sub-myid_ses-myses_voi-ACC_acq-svs_ECC_mrs.nii.gz

path/file = /tmp/testd/ACC_svs_noECC.nii.gz
old file  = ACC_svs_noECC.nii.gz
new file  = sub-myid_ses-myses_voi-ACC_acq-svs_noECC_mrs.nii.gz

path/file = /tmp/testd/ACC_svs_ref.nii.gz
old file  = ACC_svs_ref.nii.gz
new file  = sub-myid_ses-myses_voi-ACC_acq-svs_ref_mrs.nii.gz

path/file = /tmp/testd/Lt Hippocampus_svs_ECC.nii.gz
old file  = Lt Hippocampus_svs_ECC.nii.gz
new file  = sub-myid_ses-myses_voi-Lt Hippocampus_acq-svs_ECC_mrs.nii.gz

path/file = /tmp/testd/Lt Hippocampus_svs_noECC.nii.gz
old file  = Lt Hippocampus_svs_noECC.nii.gz
new file  = sub-myid_ses-myses_voi-Lt Hippocampus_acq-svs_noECC_mrs.nii.gz

path/file = /tmp/testd/Lt Hippocampus_svs_ref.nii.gz
old file  = Lt Hippocampus_svs_ref.nii.gz
new file  = sub-myid_ses-myses_voi-Lt Hippocampus_acq-svs_ref_mrs.nii.gz

path/file = /tmp/testd/Lt Hippocampus_svs_ref.json
old file  = Lt Hippocampus_svs_ref.json
new file  = sub-myid_ses-myses_voi-Lt Hippocampus_acq-svs_ref_mrs.json


oldfilename = Lt Hippocampus_svs_ref.json
newfilename = sub-myid_ses-myses_voi-Lt Hippocampus_acq-svs_ref_mrs.json

Я не совсем понимаю решение. Переменная $bidsdir, указывающая путь к папке, в которой расположены 6 файлов (12, если считать jsons), вообще не используется в коде. А что такое file.list?

Julia 10.06.2024 19:26

Не уверен, что это абсолютно верно: вы бы знали ;)

goose@t410:/tmp/brain$ find
.
./Lt Hippocampus_svs_ECC.nii.gz
./Lt Hippocampus_svs_ref.nii.gz
./ACC_svs_noECC.nii.gz
./Lt Hippocampus_svs_noECC.nii.gz
./ACC_svs_ECC.nii.gz
./ACC_svs_ref.nii.gz
goose@t410:/tmp/brain$ rename  -E "s/(ACC|Lt Hippocampus)/sub-${id}_ses-${ses}_voi-\1_acq/" -E "s/(ref|ECC|noECC)/\1_mrs/"   -E 's/acq_svs/acq-svs/' *.gz
\1 better written as $1 at (eval 25) line 2.
\1 better written as $1 at (eval 25) line 3.
goose@t410:/tmp/brain$ find
.
./sub-_ses-_voi-Lt Hippocampus_acq-svs_ref_mrs.nii.gz
./sub-_ses-_voi-ACC_acq-svs_ref_mrs.nii.gz
./sub-_ses-_voi-Lt Hippocampus_acq-svs_ECC_mrs.nii.gz
./sub-_ses-_voi-ACC_acq-svs_ECC_mrs.nii.gz
./sub-_ses-_voi-ACC_acq-svs_noECC_mrs.nii.gz
./sub-_ses-_voi-Lt Hippocampus_acq-svs_noECC_mrs.nii.gz

Другие вопросы по теме