使用bash工具提取子字符串,直到并包括匹配的单词

时间:2018-10-11 14:33:01

标签: bash

我有这样的文件名:

func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz
func/sub-01_task-pfobloc_run-01_bold_space-T1w_preproc.nii.gz
func/sub-01_task-rest_run-01_bold_space-T1w_preproc.nii.gz

,并且我想从每个文件名中提取该部分,直到并包括单词bold,以便最终得到:

func/sub-01_task-biommtloc_run-01_bold
func/sub-01_task-pfobloc_run-01_bold
func/sub-01_task-rest_run-01_bold

有什么想法怎么做?

7 个答案:

答案 0 :(得分:3)

最简单的方法是删除bold及其后的所有内容,然后替换bold。显然,这种情况只有在终止字符串固定的情况下才有效。

$ f=func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz
$ echo "${f%%bold*}"
func/sub-01_task-biommtloc_run-01_
$ echo "${f%%bold*}bold"
func/sub-01_task-biommtloc_run-01_bold

答案 1 :(得分:1)

您想要这样的东西吗?

echo func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz | sed -e 's#bold_.*$#bold#'

希望这会有所帮助

答案 2 :(得分:0)

(不必要)这很聪明:删除以“ bold”结尾的前缀  然后根据剩余的后缀长度进行一些子字符串索引运算:

$ file=func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz
$ tmp=${file#*bold}
$ keep=${file:0:${#file}-${#tmp}}
$ echo "$keep"
func/sub-01_task-biommtloc_run-01_bold

如果$ file不包含“ bold”,则$ keep将为空:如果为空,我们可以给它$ file的值:

$ file=foobar
$ tmp=${file#*bold}
$ keep=${file:0:${#file}-${#tmp}}
$ : ${keep:=$file}
$ echo "$keep"
foobar

但是请认真做what chepner suggests

答案 3 :(得分:0)

使用Perl

> echo "func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz" | perl -e 'while (<>) { $_=~s/(.*bold)(.*)/\1/g; print } '
func/sub-01_task-biommtloc_run-01_bold
>

答案 4 :(得分:0)

这类似于glenn的解决方案,但是有点“不太聪明”,因为它不使用子字符串,而只是嵌套替换:

$ while IFS= read -r fname; do echo "${fname%"${fname#*bold}"}"; done < infile
func/sub-01_task-biommtloc_run-01_bold
func/sub-01_task-pfobloc_run-01_bold
func/sub-01_task-rest_run-01_bold

替换"${fname%"${fname#*bold}"}"说:

  • 从每个文件名的末尾删除"${fname#*bold}"
  • "${fname#*bold}"是从文件名开头删除的bold之前的所有内容

第一个包含显式中间步骤的文件名的示例:

$ fname=func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.gz
$ echo "${fname#*bold}"
_space-T1w_preproc.nii.gz
$ echo "${fname%"${fname#*bold}"}"
func/sub-01_task-biommtloc_run-01_bold

答案 5 :(得分:0)

f=func/sub-01_task-biommtloc_run-01_bold_space-T1w_preproc.nii.g
echo "${f//bold*/bold}"

答案 6 :(得分:-1)

我建议使用sed来完成此任务。首先,将所有输入的文件名粘贴到文件中,在当前目录中将其命名为namelist.txt。只要您的sed支持扩展的正则表达式(多数情况下,尤其是GNU sed),以下内容将起作用。请注意,平台之间扩展正则表达式的标志可能有所不同,请查看sed手册页。在我的Linux上是-r

bash -c "sed -r 's/(sub-01_task-.{1,10}_run-01_bold).+/\\1/' namelist.txt"