마지막 밑줄 문자에서 문자열을 자르는 방법은 무엇입니까?

마지막 밑줄 문자에서 문자열을 자르는 방법은 무엇입니까?

다음과 같은 파일 목록이 있습니다.

[root@ods1 backup]# ls -l
total 93892810
-rw-r----- 1 root root 651248 Feb 17 08:34  abc_def_g_17-02-2022.sql
-rw------- 1 root root 665248 Mar 23 08:46  bbc_23-03-2022.sql
-rw-r----- 1 root root 676992 Apr 04 16:52  zz_b_04-04-2022.sql

내가 달성해야 할 것은 다음과 같습니다.

abc_def_g
bbc
zz_b

나는 성공하지 않고 이것을 시도했습니다.

ls -l | awk '{print $9}' | cut -d '_' -f1-2

이 목표를 어떻게 달성할 수 있나요? 마지막 줄까지 일련의 명령을 가져옵니다._캐릭터는 직업에 달려 있어야합니다.

편집: 이 명령은 CentOS 8에서 실행됩니다.

답변1

도착하다파싱되지 않음lsloop, 간단 하고 구문을 사용할 수 있습니다 shell.

for f in *; do echo "${f%_*}"; done

목록을 추가로 처리해야 하는 경우(그리고 배열로 작업할 수 있는 셸이 있는 경우) 항목을 배열에 추가할 수 있습니다.

tokens=()
for f in *; do tokens=("${tokens[@]}" "${f%_*}"); done
echo "${tokens[@]}"

또는 루프를 사용하지 않고 배열을 직접 선언합니다.

files=(*)
tokens=("${files[@]%_*}")
#or
for token in "${files[@]%_*}"; do echo "$token"; done

답변2

다음과 같이 시도해 볼 수 있습니다.

ls|awk -F_ '{NF-=1}1' OFS=_

여기서의 비결은 필드 수를 하나씩 줄이는 것입니다(마지막 필드 제거).

답변3

zsh쉘 에서 :

print -r -C1 -- *_*.sql(Ne['REPLY=${REPLY%_*}'])

*_*.sql이는 glob 한정자를 사용하여 마지막 밑줄을 포함하여 마지막 밑줄 뒤의 모든 항목을 제거하여 주어진 glob 패턴과 일치하는 이름을 수정합니다. 실제 대체는 표준 매개변수 대체를 사용하여 수행됩니다.

결과 문자열을 사용하여 인쇄 이외의 작업을 수행하려면 대신 와일드카드 패턴을 사용하십시오 print(예: for루프에서 또는 다른 명령에 대한 인수로). print위 명령을 명령 대체에 넣지 마십시오 !

답변4

출력을 구문 분석하지 않습니다.ls:

$ awk 'BEGIN{for (i=1;i<ARGC;i++) { f=ARGV[i]; sub(/_[^_]*$/,"",f); print f }; delete ARGV}' *
abc_def_g
bbc
zz_b

이는 파일 이름에 개행 문자나 다른 문자가 포함된 경우에도 작동합니다.

관련 정보