1

2 つの質問があります。.txt ファイルを含むサブフォルダーを含むフォルダーがあります。txt ファイルの形式は次のとおりです。

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

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

次の 3 つの情報を引き出したいと思います。

  1. タイトル (ピリオドの代わりにスペースを使用) 例: to kill a mockingbird
  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 変数は正しく出力されますが、vol および issue number 変数はファイル名を出力するだけです...

4

2 に答える 2

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
于 2013-03-11T00:35:26.120 に答える
0

話者による解決策おそらく最善ですが、私はまだ古い学校で好きsedです。

セミコロンで区切っsedた単一の引数、または複数の引数で複数のコマンドを指定できます。私は通常後者を使用します。また、名前をクリーンアップして、先頭のパスを削除します。次に、notの拡張正規表現を使用しているかどうかを判断する必要があります。また、使用するものに一貫性を持たせる必要があります。-e-efind

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 に答える