분리 계를 기반으로 변수를 추출하기 위해 bash 변수 대체를 사용할 수 있습니까? 파일 이름 (이 경우 foo
)의 즉각적인 디렉토리 이름을 가져 오려고합니다.
$ filename=./foo/bar/baz.xml
echo $filename | cut -d "/" -f 2
또는
echo $filename | awk -F "/" "{print $2}"
같은 것을 할 수 있다는 것을 알고 있습니다. ” 여러 파일 이름에 대해 awk
/ cut
를 포크하는 속도가 느려집니다.
다양한 솔루션에 대해 약간의 프로파일 링을 수행했습니다. , 내 실제 파일 사용 :
echo | 컷 :
real 2m56.805s user 0m37.009s sys 1m26.067s
echo | awk :
real 2m56.282s user 0m38.157s sys 1m31.016s
@steeldriver “s 변수 대체 / 쉘 매개 변수 확장 :
real 0m0.660s user 0m0.421s sys 0m0.235s
@jai_s “s IFS-wrangling :
real 1m26.243s user 0m13.751s sys 0m28.969s
두 제안 모두 내 기존 아이디어보다 크게 개선되었지만 변수 대체가 가장 빠릅니다. 새로운 프로세스를 포크해야합니다.
댓글
- gnu.org/software/bash/manual / html_node / …
- 모든 파일 이름을 awk의 한 번 호출로 보내면 순수한 bash의 어떤 솔루션보다 훨씬 빠릅니다.
- 배열을 사용할 수 없습니다. 한 번에 모두 수행 한 다음 새 배열에 넣습니까?
답변
*/
tmp="${filename#*/}"
와 일치하는 가장 짧은 선행 하위 문자열을 제거한 다음 가장 긴 /*
답변
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
댓글
- 좋습니다.
- 이것은 일반적으로 선호하는 방법이지만 Bash는 이 구문을 사용하여
$1
에서$9
까지만 지원합니다. 10 번째 이후 인수의 경우${10}
양식을 사용해야합니다. - iv id가 ' 일 때 작동하지 않습니다. = “36d3dafb01″>
에는 와일드 카드가 포함됩니다. 그리고 나중에 IFS
를 복원해야합니다 (또는 명령 대체에서이 작업을 수행하여 필드 값을 가져 오면 후행 줄 바꿈이 제거됩니다).
echo: write error: Bad address
. unset IFS
해야합니다. 답변
피드 속도를 높이기 위해 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
Answer
이 모든 awk / sed / 대신”dirname “명령을 사용하지 않는 이유 잘라내시겠습니까?
filename=./foo/bar/baz.xml dirname $filename
수익 :
./foo/bar
댓글
- 이 경우에는 전체 디렉토리 경로가 아닌 직접적인 디렉토리를 찾고있었습니다.