bash 변수 대체를 사용하여 구분 기호를 기반으로 변수의 일부를 추출할 수 있습니까? 파일 이름의 직접 디렉터리 이름을 얻으려고 합니다(이 경우 foo
).
$ filename=./foo/bar/baz.xml
나는 내가 다음과 같은 일을 할 수 있다는 것을 안다.
echo $filename | cut -d '/' -f 2
또는
echo $filename | awk -F '/' '{print $2}'
awk
그러나 분기/ cut
여러 파일 이름은 매우 느려집니다.
실제 파일을 사용하여 다양한 솔루션에 대한 분석을 수행했습니다.
에코|컷:
real 2m56.805s
user 0m37.009s
sys 1m26.067s
에코 |
real 2m56.282s
user 0m38.157s
sys 1m31.016s
@steeldriver의 변수 대체/쉘 매개변수 확장:
real 0m0.660s
user 0m0.421s
sys 0m0.235s
@jai_s의 IFS 인수:
real 1m26.243s
user 0m13.751s
sys 0m28.969s
두 제안 모두 기존 아이디어에 비해 크게 개선되었지만 새로운 프로세스를 포크할 필요가 없기 때문에 변수 대체가 가장 빠릅니다.
답변1
일치 항목의 가장 짧은 선행 하위 문자열을 제거할 수 있습니다.*/
tmp="${filename#*/}"
그런 다음 일치하는 가장 긴 후행 하위 문자열을 제거합니다./*
echo "${tmp%%/*}"
답변2
echo $f
a/b/c
$ (IFS='/';set $f; echo $1)
a
$ (IFS='/';set $f; echo $2)
b
$ (IFS='/';set $f; echo $3)
c
와일드카드를 사용하면 큰따옴표나 작은따옴표와 함께 작동하는 것 같습니다.
f="a?b?c"
$(IFS="?"; set $f; echo $1)
a
echo $f
a*b*c
(IFS="*"; set $f; echo $1)
a
예, IFS를 기본값으로 복원해야 합니다.
unset IFS
답변3
작업 속도를 높이 려면 목록을 피드하세요 awk
.
awk -F '/' '{print $2}' < <(find /usr)
awk -F '/' '{print $2}' < inputfile
데모:
time awk -F '/' '{print $2; SUM++} END {print "number of directories found: " SUM}' < <(find /usr -type d)
usr
usr
.
.
number of directories found: 16748
real 0m8.910s
user 0m0.050s
sys 0m0.050s
답변4
awk/sed/cut 대신 "dirname" 명령을 사용하면 어떨까요?
filename=./foo/bar/baz.xml
dirname $filename
생산하다:
./foo/bar