現在作業中の場所のファイル名の一部を抽出しようとしていますが、予想される出力とは機能しません。
サンプル:
ls -a *0728*dat | ls -a *0728*dat |種類
amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat
amnbmnb_kjhkj_07282019_11_23_22.dat
njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat
ファイル名からファイル部分、病棟日の左側のすべての項目(アンダースコア(_)を含む)を抽出して変数に割り当てたいと思います。
希望の出力:
変数ファイルは、forループに渡すために値を保持するために必要なファイルです。
文書:
amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_
for file_name in "${file[@]}"
do
echo " file_name=$file_name"
done
希望の出力:
amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_
答え1
おそらく:
for file_name in *0728*dat
do
printf '%s\n' "${file_name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9]_[0-9][0-9].dat}"
done
これにより、各ファイル名の末尾に8桁、アンダースコア、2桁、アンダースコア、2桁、アンダースコア、2桁、。などのパターンが削除されます.dat
。
答え2
sedを使用してください:
ls -a *0728*dat | sed 's/[0-9].*//'
amnbmnb_kjhkj_
amnbmnbm_jnjmnm_sd_
njnkjnjk_AbnBCBB_DE_
または
ls -a *0728*dat | sed "s/[0-9]\{8\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}\.dat$//"
答え3
以下にはbash
、4.4以上、GNUfind
とGNU sed
(または出力/入力区切り文字でNULをサポートする少なくともaとa find
)が必要です。sed
$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 |
sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')
先行、日付と時刻、および.dat拡張子を削除files
したら、現在のディレクトリから一致するファイル名でbash配列()を入力します。 NULをレコード(つまりファイル名)区切り文字として使用して、すべてのファイル名でスペース、改行、シェルメタ文字などに関連する潜在的な問題を回避します。./
sed
find
出力をls
他のプログラムの入力として使用したり、他のプログラムのコマンドラインで引数として使用したりしないでください。これは安全ではなく信頼できません。バラよりなぜいいえ解析ls
(および実行方法)?
もちろんfind
、コマンドを変更して他のパターンと一致するファイルを見つけたり、サブディレクトリなどを見つけることもできます。
例:
$ touch amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat amnbmnb_kjhkj_07282019_11_23_22.dat \
njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat
$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 |
sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')
$ typeset -p files
declare -a files=([0]="amnbmnbm_jnjmnm_sd_" [1]="amnbmnb_kjhkj_" [2]="njnkjnjk_AbnBCBB_DE_")
$ printf '%s\n' "${files[@]}"
amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_