Cut/awk 대신 bash 변수 대체 사용

Cut/awk 대신 bash 변수 대체 사용

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

관련 정보