【问题标题】:Split filename and get the element between first and last occurrence of underscore拆分文件名并获取第一次和最后一次出现下划线之间的元素
【发布时间】:2017-07-11 00:27:29
【问题描述】:

我正在尝试在 for 循环中拆分许多文件夹名称,并提取文件名的第一个和最后一个下划线之间的元素。文件名可能类似于 ENCSR000AMA_HepG2_CTCF 或 ENCSR000ALA_endothelial_cell_of_umbilical_vein_CTCF。

我的问题是文件夹名称在下划线总数中彼此不同,所以我不能使用类似的东西:

IN=$d
folderIN=(${IN//_/ })
tf_name=${folderIN[-1]%/*} #get last element which is the TF name
cell_line=${folderIN[-2]%/*}; #get second last element which is the cell line
dataset_name=${folderIN[0]%/*}; #get first element which is the dataset name

cell_line 可以是一个或多个由下划线分隔的单词,但始终位于第一个和最后一个下划线之间。

有什么帮助吗?

【问题讨论】:

    标签: bash for-loop split substring


    【解决方案1】:

    只需在两步 bash 参数扩展中执行此操作,因为与 zsh 或其他 shell 不同,bash 不支持嵌套参数扩展。

    "${string%_*}" 删除最后一次出现“_”之后的所有内容,"${tempString#*_}" 删除从开始到第一次出现“_”的所有内容

    string="ENCSR000ALA_endothelial_cell_of_umbilical_vein_CTCF"
    tempString="${string%_*}"
    printf "%s\n" "${tempString#*_}"
    endothelial_cell_of_umbilical_vein
    

    另一个例子,

    string="ENCSR000AMA_HepG2_CTCF"
    tempString="${string%_*}"
    printf "%s\n" "${tempString#*_}"
    HepG2
    

    您可以修改此逻辑以应用于文件夹中的每个文件名。

    【讨论】:

      【解决方案2】:

      可以使用正则表达式。

      extract_words() {
          [[ "$1" =~ ^([^_]+)_(.*)_([^_]+)$ ]] && echo "${BASH_REMATCH[2]}"
      }
      
      while read -r from_line
      do
          extracted=$(extract_words "$from_line")
          echo "$from_line" "[$extracted]"
      done < list_of_filenames.txt
      

      编辑:我将“提取”移动到一个单独的 bash 函数中,以便在更复杂的情况下重用和轻松修改,例如:

      extract_words() {
              perl -lnE 'say $2 if /^([^_]+)_(.*)_([^_]+)$/' <<< "$1"
      }
      

      【讨论】:

      • 您不需要命令替换;让extract_words 调用[[ 命令即可; BASH_REMATCH 是全局设置的,所以你可以写 extract_words "$from_line" &amp;&amp; extracted=${BASH_REMATCH[2]}
      • @chepner 当然。但前提是您使用内置的 bash 正则表达式。如果有人将extract_words's 内容替换为一些awkperl(对于更复杂的场景),则需要进行命令替换。正如我所写,它是为易于修改而设计的。 (并且因为替换实际上调用了一个 bash 函数,它不会伤害):D
      • 这将是更改为extract_words 的人的问题。我认为适应未来对代码的修改不值得在不必要的情况下进行分叉的开销。
      • @chepner 好的,很公平。要点,例如回答了 OP 的问题,回答了如何提取想要的字符串。可以使用 bash_regexes 一次性完成。周围的一切都取决于读者...... :)
      猜你喜欢
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      相关资源
      最近更新 更多