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

时间:2013-03-10 23:51:56

标签: bash sed

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

{title.of.a.book}.V{4 digit year}.{4 digit issue}.txt

例如

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

我想提取三条信息:

  1. title(用空格而不是句号)例如:杀死一只模仿鸟
  2. 卷号例如:1960
  3. 发行编号例如:0001
  4. 这是我到目前为止所写的内容

    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
    
    1. 如何将3条信息拉出来分开变量
    2. 如何用空格
    3. 替换.

      我无法决定是先重命名文件(重命名s/./ /g) - 还是之后重命名$name

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

2 个答案:

答案 0 :(得分:3)

不需要使用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

答案 1 :(得分:0)

solution speakr可能是最好的,但我还是老了,喜欢sed

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

使用GNU sed 4.4.2(©2012),我无法使用\d表示法来识别数字;这里可能有些蠢。

没有扩展的正则表达式(适用于非sed的GNU版本):

for file in $(find /home/user/books -type f -name '*.txt')
do
    base=$(basename $file .txt)
    name=$(  echo "$base" | sed -e 's/^\(.*\).V.*$/\1/' -e 's/\./ /g') # replace dots
    volume=$(echo "$base" | sed -e 's/^.*V\([0-9]\{4\}\).*$/\1/')
    issue=$( echo "$base" | sed -e 's/^.*\([0-9]\{4\}\)$/\1/')
    echo "$name" "$volume" "$issue"
done

示例书的输出:

to kill a mockingbird 1960 0001

使用GNU sed的'扩展正则表达式'模式(-r):

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

使用\d表示法(输出错误):

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