zsh에 공백이있는 요소 나열


10

이 시점에서 2 시간 동안 zsh 스크립팅을 공부하고 있는데 벽에 부딪 쳤습니다. 공백이있을 수있는 파일 목록을 살펴보고 싶습니다. zsh가 내가 연구하고있는 것이기 때문에 스크립트를 작성하려는 작업이 아니기 때문에 zsh 인 한 다음 예제와는 완전히 다른 접근법을 사용할 수 있습니다.

files=(`ls`)
for f in $files; do
    print $f
done

분명히 재생성하는 것이 아니라 루프의 각 반복마다 전체 파일 이름을 캡처하고 ls싶습니다 $f.

답변:


12

먼저, 사용 ls은 단지 예 라고 가정합니다 . ls모호하므로 쉘에서 출력을 구문 분석 할 수 없습니다 . 이것이 뉴스 인 경우 ls (1)의 출력을 구문 분석하지 않아야하는 이유를 읽으십시오 . 모든 쉘에서 파일 목록을 얻으려면 와일드 카드를 사용하십시오 (예 :) files=(*).

zsh에서는 다른 쉘과 마찬가지로 명령 대체 결과가 공백 문자 (보다 정확하게는 값에 따라)로 단어로 분할됩니다 IFS. (다른 쉘과 달리, 명령 대체 결과는 zsh에서 globbing되지 않습니다.) 따라서 ls명령 의 출력 이

hello world
wibble

다음 files=($(ls))세트 files3 개 요소를 포함하도록 배열 : hello, worldwibble.

명령 대체가 큰 따옴표로 묶인 경우 분할이 수행되지 않습니다. 매개 변수 확장 플래그를 사용하여 사용자 지정 분할을 수행 할 수 있습니다 . @분할 결과가 배열임을 나타내 려면 플래그를 사용하십시오 (이상하게는 큰 따옴표 "${(@)…}"로 묶은 문자열을 여러 단어로 확장하더라도 큰 따옴표로 확장을 유지해야합니다 ). 분할하려면 s플래그를 사용하십시오 ( 예 : "${(@s:,:)…}"쉼표로 분할). f플래그는 줄 바꿈에 분할합니다.

files=("${(@f)$(ls)}")

일반적으로 배열을 반복하는 적절한 방법은 빈 요소 for f in $files[@]$files제거하는 것입니다 (여기서는 요소가 비어 있지 않기 때문에 중요하지 않음).

print $f$fa로 시작하고에서 -백 슬래시를 확장 하면 스위치로 해석 됩니다 $f. 을 사용 print -r -- $f하거나 print -rn -- $f문자열 뒤에 줄 바꿈을 추가하지 않으려는 경우를 사용하십시오 .


감사합니다. 예, ls는 단지 예일뿐입니다. 현재 구체적인 목표는 없었습니다. 공백이있는 개별 결과가있을 수있는 명령에서 목록 요소를 인용하거나 이스케이프 처리하는 방법을 알고 싶습니다.
Felix

혼란스러워하는 한 가지 이유는 파일의 외부 () = ( "$ {(@ f) $ (ls)}")식이 @f에 필요한 이유는 무엇입니까? 그리고 (f)가 ​​외부에 나타나는 한 (f)는 잘 작동하는 것 같습니다.
Koobz

@Koobz 1. 외부 (…)files문자열이 아닌 배열 이기 때문에 필요 합니다 (이것은 명령에서 행의 연결을 포함하고에 의해 수행 된 분할을 취소합니다 (f)). 2. foo=$'one\n\nthree', contrast print -rl $ {(f) foo}`및을 사용하십시오 print "${(@f)foo}". 빈 줄을 유지하려면 큰 따옴표가 필요합니다. 빈 줄은 얻지 ls못하지만 다른 명령으로 발생할 수 있습니다.
Gilles 'SO- 악마 그만해

매우 감사. 이 광기에 운율이나 이유가 있습니까? 그럼에도 불구하고 혼란스러운 이유는 중간 값이 연결된 문자열 인 경우 외부 ()가 개별 단어에서 문자열을 다시 다시 분할하지 않는 이유입니다. 예를 들어 루비 또는 PHP의 문자열 보간처럼 보입니다.
Koobz

@Koobz 빈 단어를 특수하게 처리하는 이유는 오랫동안 잊혀진 이전 버전의 zsh와 역사적으로 호환되기 때문입니다. 자동 분할되지 않는 이유는 놀라 울뿐 아니라 종종 바람직하지 않은 동작이기 때문입니다. 자동 분할은 사용자가 지시하지 않는 한 zsh가 에뮬레이트하지 않는 Bourne 쉘의 동작입니다.
Gilles 'SO- 악마 그만

2

zsh에서는 기본적으로 단어 분할을 수행하지 않는 쉘 확장을 사용할 수 있습니다. 시험

for f in /path/to/files/*; do
    print ${f}
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.