Bash 使用sed将文件名的一部分提取到变量中

Bash 使用sed将文件名的一部分提取到变量中,bash,sed,Bash,Sed,我有两个问题。我有一个文件夹,其中包含包含.txt文件的子文件夹。txt文件的格式如下 {title.of.a.book}.V{4位数年份}.{4位数发行}.txt 范例 to.kill.a.mockingbird.V1960.0001.txt 我想拿出三条信息: 标题(用空格代替句号)如:杀死一只知更鸟 卷号eg:1960 发行编号eg:0001 这就是我到目前为止写的 for file in $(find /home/user/books -type f -name '*.txt') d

我有两个问题。我有一个文件夹,其中包含包含.txt文件的子文件夹。txt文件的格式如下

{title.of.a.book}.V{4位数年份}.{4位数发行}.txt
范例

to.kill.a.mockingbird.V1960.0001.txt
我想拿出三条信息:

  • 标题(用空格代替句号)如:杀死一只知更鸟
  • 卷号eg:1960
  • 发行编号eg:0001
  • 这就是我到目前为止写的

    for file in $(find /home/user/books -type f -name '*.txt')
    do
        name=$(echo "$file"|sed -e 's/^\(.*\).V.*txt$/\1/')
        volume=$(echo "$file"|sed -e 's/^.*V\(\d{4}\).*$/\1/')
        issue=$(echo "$file"|sed -e 's/^.*\(\d{4}\).txt$/\1/')
        echo "$name" "$volume" "$issue"
    done
    
  • 如何提取3条信息来分离变量
  • 如何用空格替换
  • 我无法决定是先重命名文件(重命名
    s///g
    ),还是之后重命名
    $name


    name变量打印正确,但volume和issue number变量只打印文件名…

    无需使用sed,bash可以通过param扩展处理它

    假设您的所有文本文件都使用上述格式:

    #!/bin/bash
    for file in $(find /home/user/books -type f -name '*.txt'); do
        pre=${file%%.txt}
        pre=${pre//./ }
        name=${pre%% V*}
        volume=${pre##* V}
        volume=${volume%% *}
        issue=${pre##* }
        echo "Name: '$name' Volume: '$volume' Issue: '$issue'"
    done
    
    by可能是最好的,但我还是个老同学,喜欢sed

    您可以在一个
    -e
    参数中(用分号分隔)或在多个
    -e
    参数中向
    sed
    提供多个命令;我通常使用后者。我还将清理
    find
    中的名称以删除前导路径。然后,您需要决定是否使用not的扩展正则表达式,并且需要在使用的内容上保持一致

    使用GNU
    sed
    4.4.2(©2012),我无法使用
    \d
    符号识别数字;这里可能有点傻

    不带扩展正则表达式(可用于非GNU版本的
    sed
    ):

    示例书的输出:

    to kill a mockingbird 1960 0001
    
    使用GNU
    sed
    的“扩展正则表达式”模式(
    -r
    ):

    使用
    \d
    符号(输出不正确):

    输出:

    to kill a mockingbird to.kill.a.mockingbird.V1960.0001 to.kill.a.mockingbird.V1960.0001
    

    这很有效,谢谢我想投赞成票,但它不让我!!这同样有效-谢谢你的帮助!我也会投赞成票,但我没有足够的声誉!!
    for file in $(find /home/user/books -type f -name '*.txt')
    do
        base=$(basename $file .txt)
        name=$(  echo "$base" | sed -r -e 's/^(.*).V.*$/\1/' -e 's/\./ /g') # replace dots
        volume=$(echo "$base" | sed -r -e 's/^.*V([0-9]{4}).*$/\1/')
        issue=$( echo "$base" | sed -r -e 's/^.*([0-9]{4})$/\1/')
        echo "$name" "$volume" "$issue"
    done
    
    for file in $(find /home/user/books -type f -name '*.txt')
    do
        base=$(basename $file .txt)
        name=$(  echo "$base" | sed -r -e 's/^(.*).V.*$/\1/' -e 's/\./ /g') # replace dots
        volume=$(echo "$base" | sed -r -e 's/^.*V(\d{4}).*$/\1/')
        issue=$( echo "$base" | sed -r -e 's/^.*(\d{4})$/\1/')
        echo "$name" "$volume" "$issue"
    done
    
    to kill a mockingbird to.kill.a.mockingbird.V1960.0001 to.kill.a.mockingbird.V1960.0001