1

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

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

例子

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

我想提取三个信息:

  1. 标题(用空格代替句点)例如:杀死一只知更鸟
  2. 卷号 例如:1960
  3. 问题编号 例如: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
  1. 如何提取 3 条信息来分隔变量
  2. 如何.用空格替换

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

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

4

2 回答 2

3

不需要使用 sed,bash 可以通过参数扩展来处理它。

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

#!/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
于 2013-03-11T00:35:26.120 回答
0

演讲者的解决方案可能是最好的,但我仍然是老派,喜欢.sed

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

使用 GNU sed4.4.2 (©2012),我无法获得\d识别数字的符号;这里可能有一些愚蠢的东西。

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

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

使用 GNUsed的“扩展正则表达式”模式 ( -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
于 2013-03-11T06:20:23.117 回答