次の形式のファイルがたくさんあります。
2014-11-19.8.ext
2014-11-26.1.ext
2014-11-26.2.blah.ext
2014-11-26_3.ext
2014-11-26.4.stuff_here.ext
2014-12-03.1. could be anything.ext
2014-12-032b.ext
2014-11-26 613 adva.ext
私の目標は、ファイルの全リストを繰り返して日付形式を取得し、それを処理するために変数にYYYY-MM-DD
保存することです(私の場合はコマンドYYYYMMDD
にプッシュされます)。touch
したがって、通常は次の正規表現と一致します。(\d{4})-(\d{2})-(\d{2}).*
次に、を使用して目的のパターンを取得しましたが、/でこれを行う$1$2$3
方法がわかりません。bash
zsh
シェルスクリプトでこれを行うにはどうすればよいですか?
答え1
使用パラメータ拡張
$ touch 2014-11-19.8.ext 2014-11-26.1.ext
$ for f in *.ext; do d="${f:0:4}${f:5:2}${f:8:2}"; echo "$d"; done
20141119
20141126
${f:0:4}
変数名であるindexから始めて4文字を表します0
。f
echo "$d"
あなたのコードに置き換えてください。
答え2
現在のディレクトリ内の各ファイルを繰り返し、ファイル名を目的のパターンと比較するには、日付フラグメントを含む変数を設定します。
for f in *
do
[[ $f =~ ^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])(.*) ]] &&
yourvar="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
done
これは以下を使用します。[[
正規表現マッチングを使用するbash関数日付フラグメントを BASH_REMATCH 配列に入れます。
答え3
次のコマンドを使用して、対話的にこれを実行できますGNU sed
。
$ sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}.*\)/\1\2\3/g' stuff.txt
複数のファイルの場合(同じディレクトリにあり、そのディレクトリに考慮される他のファイルがない場合):
for file in *
do
if [ -f "$file" ]
then
sed 's/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\).*/\1\2\3/g' "$file"
fi
done
答え4
GNU Coreutils を使用すると、以下が表示されます。
$ date --date=2014-11-13 +"%Y%m%d"
20141113
しかし:
$ date --date=2014-11-130ABCJUNK +"%Y%m%d"
date: invalid date ‘2014-11-130ABCJUNK’
したがって、作業ははるかに簡単です。YYYY-MM-DDetc
各ファイル名の最初の10文字を抽出して日付自体を取得し、それをdate
再フォーマットするために渡します。
ただし、GNU Coreutilsを使用している場合はまったく同じオプションがあるため、そのdate
コマンドをスキップできます。touch
--date=STRING
for file in * ; do
date=${file%${file##??????????}} # chop all but first ten
touch --date=$date -- "$file"
done
touch
ところで、GNU Coreutilsに依存するときにPOSIX移植可能な方法で10文字のスライスを実行するのはなぜですか?
for file in * ; do
date=${file:0:10}
touch --date=$date -- "$file"
done