Я хочу извлечь некоторую информацию из имен файлов, используя регулярное выражение в 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)
все имена файлов имеют ровно два подчеркивания и две точки? если мы удалим все после точек, у нас останется строка с двумя разделителями подчеркивания... будет ли эта часть имени файла всегда иметь формат brain-region + _ + литеральная строка svs + _ + type?
в коде упоминается ext, это может быть .json ... пожалуйста, обновите образец данных, включив в него пару файлов с расширением .json
[[ $file =~ (ACC|Lt Hippocampus)_svs_(ECC|noECC|ref).*(nii[.]gz|json)$ ]] && declare -p BASH_REMATCHBash использует синтаксис расширенных регулярных выражений POSIX. RE, который вы показали, но не используете, не соответствует этому синтаксису.
@markp-fuso Я не добавлял файлы .json для экономии места. Файлы .json являются дополнительными к .nii.gz, поэтому имена файлов точно такие же, за исключением расширения. Что касается вашего второго вопроса – да. Примеры, которые я привел, представляют собой все возможные варианты имен файлов.
@Шон, я не знаю, что это значит. Обычно я использую regex101 для написания регулярного выражения, а затем нажимаю «python» слева. У меня нет другого опыта регулярных выражений, поэтому мой вопрос
пожалуйста, обновите вопрос, указав дополнительную информацию; не все будут читать комментарии, пытаясь собрать воедино всю картину
То, что сказал @Shawn, означает, что регулярное выражение, которое у вас есть в вашем вопросе (которое выглядит так, как будто это может быть регулярное выражение, несовместимое с POSIX Perl, то есть PCRE, возможно, с некоторыми python-измами, я не знаю), не является хорошей отправной точкой для написание регулярного выражения, понятного bash (т. е. POSIX-совместимого расширенного регулярного выражения, ERE).
Пожалуйста, отредактируйте свой вопрос, чтобы показать ожидаемый результат — ваши требования еще не ясны, а образец входных данных — это только половина того, что нам нужно, чтобы протестировать потенциальное решение.
@EdMorton более эффективно использовать itertools.product в Python, таким образом вы можете легко сгенерировать ожидаемый результат на основе информации в сообщении. рад поделиться кодом, если вы не знаете, как это сделать. Но это также указано в ответе ниже (хотя код не работает).
рассмотрите возможность просмотреть минимальный воспроизводимый пример и затем соответствующим образом обновить вопрос; имейте в виду, что большинство людей, просматривающих этот вопрос, возможно, не знают, что такое файлы BIDS и sidecar, и в этом случае это не имеет значения, важно (очень) основное требование для анализа имени файла; если у вас есть время оставлять комментарии и предлагать python/itertools код для генерации желаемого результата, то его не составит труда запустить python/itertools в вашей системе и просто вырезать и вставить результат в вопрос
@markp-fuso Я думаю, что результат очевиден, исходя из моего вопроса (т. е. переменной newfilename), особенно учитывая комментарии, которые я предоставил рядом с переменными voi и type. Я также написал, какая часть кода не работает, в комментарии к этому ответу (обратите внимание, что мой комментарий был оставлен 5 часов назад, а ответ был отредактирован 4 часа назад).
@Джулия, я думаю, ты ответил не тому человеку, поскольку твой комментарий кажется не имеющим отношения к моему.
Я не понимаю, где в вашем сценарии вы применяете регулярное выражение. Кроме того, многие детали (например, петля for) не имеют отношения к проблеме. Создайте простой воспроизводимый пример вашей проблемы, покажите свою попытку ее решения и объясните, где ваша попытка не удалась.
@user1934428 user1934428 Это потому, что я не применяю регулярное выражение, потому что не знаю как (именно поэтому и задаю этот вопрос). Как я могу создать более воспроизводимый пример, если я уже предоставил все, что умею делать. Если вы не знаете ответа после того, как я указал все, что знаю, или если вы понимаете вопрос, вы можете просто нажать на другой вопрос. Однако вы решили прокомментировать уже решенный вопрос, просто чтобы сказать мне, что мой вопрос глупый.
Многие люди пытаются использовать оператор регулярного выражения bash, но делают это неправильно, поэтому вполне нормально иметь вопрос об этом, что свидетельствует о попытке сделать это. Оператор регулярного выражения внутри команды [[ ... ]] записывается как =~, и если вы просмотрите справочную страницу bash для этой строки, вы быстро найдете объяснение того, как его использовать, а также ссылку на язык регулярных выражений, поддерживаемый bash (который не такой мощный, как тот, который вы используете в Python). Кроме того, поиск в Google примеров регулярных выражений bash дает вам множество результатов, поэтому мы можем ожидать, что вы хотя бы попытаетесь это сделать.
См., например, страницу stackoverflow как задать вопрос и ответы к этому обсуждению, где подсказки, как улучшить ваш вопрос.





Предположения:
<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?
Не уверен, что это абсолютно верно: вы бы знали ;)
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
обновите код, чтобы показать, где вы устанавливаете и ссылаетесь на регулярное выражение; также обновите код, чтобы показать, что вы назначаете переменным
voi,typeиext.