현재 작업 중인 위치에 대한 파일 이름의 일부를 추출하려고 하는데 예상한 출력과 작동하지 않습니다.
견본:
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 이상, GNU find
및 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_