폴더가 있고 ls
그 폴더에서 실행하면 출력됩니다.
t-1-myFirstTest.c
myFile.c
t-42-my_second_test.c
t-3-test1234.c
.
.
.
mySecondFile.c
t-21-tset241.c
t-
개행 문자와 와 second 사이의 숫자를 제외한 모든 내용을 해당 텍스트에서 제거하고 싶습니다 -
. 따라서 이전 출력의 출력은 다음과 같아야 합니다.
1
42
3
.
.
.
21
해결책이 있지만 꽤 나쁘다고 생각합니다. 우리가 말하는 폴더가 실제로 현재 디렉터리에 있는 경우 다음을 사용합니다.
ls | grep -o -E t-[0-9]+-[a-zA-Z0-9_]+.c | grep -o -E t-[0-9]+ | grep -o -E [0-9]+
동일한 작업을 수행하는 더 좋은 방법이 있습니까?
답변1
출력을 구문 분석하는 것은 ls
나쁜 생각입니다(출력은 ls
보기 위한 것입니다). 질문 참조 "왜 `ls`를 구문 분석하지 *않나요*?".
방법은 다음과 같습니다 /bin/sh
.
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
number=${filename#t-} # remove "t-" from start of filename
number=${number%%-*} # remove everything from first "-" in what remains
printf '%s\n' "$number"
done
이는 이름이 패턴과 일치하는 현재 디렉토리의 모든 파일 이름을 반복합니다 t-*-*.c
. 각 이름에 대해 비트 t-
는 첫 번째에서 제거되고 두 번째 -
와 그 이후의 모든 항목은 다른 매개변수 확장을 통해 제거됩니다.
확장은 다음에서 ${variable#word}
(가장 짧은) 일치 항목을 제거 합니다.word
시작of $variable
, while 에서 ${variable%%word}
(가장 긴) 일치 항목을 제거합니다.word
끝끈.
bash
파일 이름과 일치하는 정규식을 사용하십시오 .
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
if [[ "$filename" =~ ^t-([0-9]+)- ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
fi
done
t-
그러면 각 파일 이름에서 다음 숫자가 일치하고 캡처됩니다. ${BASH_REMATCH[1]}
일치가 성공적으로 이루어지면 캡처된 번호 그룹을 사용할 수 있습니다. 인덱스는 1
정규식의 첫 번째 캡처링 그룹(괄호)을 나타냅니다.
느리지만 잠재적으로 편안한("익숙한") 솔루션을 위해 외부 명령을 호출하여 관심 있는 문자열 비트를 구문 분석할 수 있습니다.
for filename in t-*-*.c; do
[ ! -f "$filename" ] && continue
cut -d '-' -f 2 <<<"$filename"
done
이는 루프에서 호출 bash
할 수 있다고 가정합니다. cut
이는 쉘 자체의 내장 작업을 사용하는 것보다 훨씬 느립니다. 여기의 명령은 cut
전달된 문자열에서 두 번째로 구분된 필드를 반환하도록 요청됩니다("here-string" 리디렉션 사용).-
bash
답변2
결과에 따라 다음을 수행합니다.
ls|awk -F"-" '{print $2}'
t-
작동해야 하지만 이 부분을 고려하고 싶다면
ls|grep ^t-|awk -F"-" '{print $2}'
또는
ls|awk -F"t-" '{print $2}'|awk -F"-" '{print $1}'
답변3
귀하의 예를 기반으로 파일 목록을 만들 때 ls
다음과 같이 정렬합니다.
$ ls -1
myFile.c
mySecondFile.c
t-1-myFirstTest.c
t-21-tset241.c
t-3-test1234.c
t-42-my_second_test.c
따라서 다음 bash 함수는 파일의 개행 문자와 번호를 동일한 순서로 출력합니다.
줄바꿈과 t-와 두 번째 사이의 숫자를 제외한 모든 텍스트를 제거하고 싶습니다.
이에 대한 내 해석은 일치하지 않는 파일 이름은 t-
"줄 바꿈을 제외하고 제거"해야 한다는 것입니다. 즉, 이러한 파일 이름에 대해 빈 줄을 출력하지만 그렇지 않으면 대시 사이의 숫자를 출력합니다.
lsnums ()
{
for f in *
do
if [[ "$f" =~ t-([[:digit:]]+)- ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
else
echo
fi
done
}
결과 출력은 다음과 같습니다.
$ lsnums
1
21
3
42
...여기서 두 개의 빈 줄은 my
대신으로 시작하는 첫 번째 파일 유형 에 해당합니다 t-
.
답변4
이는 다음과 같이 간단하게 수행할 수 있습니다.
ls | cut -d '-' -f 2