파일 이름의 각 문자를 반복하는 방법은 무엇입니까?

파일 이름의 각 문자를 반복하는 방법은 무엇입니까?

for그래서 외부 루프는 디렉토리의 모든 파일을 반복하고 내부 for루프는 해당 파일 이름의 모든 문자를 반복하는 간단한 중첩 루프가 있습니다 .

#!/bin/bash

if [ $# -lt 1 ]
then
        echo "Please provide an argument"
        exit
fi

for file in `ls $1`
do
        for ch in $file
        do
                echo $ch
        done
done

위 스크립트는 작동하지 않습니다. 내부 루프는 파일 이름의 모든 문자를 반복하지 않고 전체 내용을 반복합니다.

고쳐 쓰다:

@ilkkachu의 답변을 바탕으로 다음 스크립트를 생각해 낼 수 있었고 예상대로 작동합니다. 하지만 for...in루프를 사용하지 않고 문자열을 반복 할 수 있는지 궁금합니다 .

#!/bin/bash

if [ $# -lt 1 ]
then
        echo "Please provide an argument"
        exit
fi

for file in `ls $1`; do
        for ((i=0; i<${#file}; i++)); do
                printf "%q\n" "${file:i:1}"
        done
done

답변1

Bash를 사용하고 있으므로:

#!/bin/bash
word=foobar
for ((i=0; i < ${#word}; i++)); do
   printf "char: %q\n" "${word:i:1}" 
done

${var:p:k}주어진케이var위치에서 시작하는 문자, ${#var}는 내용의 길이입니다 var. printf %q명시적인 형식으로 출력을 인쇄합니다 $'\n'. 예를 들어 개행 문자는 .

답변2

문자열이 수백자를 초과하는 경우(예, 파일 이름의 경우 가능성 없음) 문자열 길이에 대해 for 루프를 사용하고 인덱스에서 문자를 추출하는 속도가 i매우 느려집니다.

이 답변은 고급 bash 기술을 사용합니다.

while IFS= read -r -d "" -n 1 char; do
    # do something with char, like adding it to an array
    chars+=( "$char" )
done < <(printf '%s' "$string")

# inspect the array
declare -p chars

이것은프로세스 교체문자열을 읽는 동안 루프로 리디렉션합니다. 나는 printf문자열 끝에 개행 문자를 추가하는 것을 피하는 데 사용합니다. 프로세스 대체를 사용하는 주요 이점 printf ... | while read ...은 루프가 발생한다는 것입니다.현재의쉘이 아니라아들껍데기.

나는 느림의 정도에 대해 궁금해하곤 했습니다.벤치마킹.

답변3

완전성을 위해 질문에 태그가 지정되어 있어도, POSIX 셸 기능만 사용하는 대안:

#!/bin/sh
for fname
do
  while [ "${#fname}" -ge 1 ]
  do
    rest=${fname#?} char=${fname%"$rest"} fname=$rest
    printf '%s\n' "$char"       # Do something with the current character
  done
done

내부 루프의 역할:

  • 첫 번째 문자를 뺀 값으로 설정합니다 rest.fname

  • rest삭제된 단일 문자를 에 할당 fname합니다 char.

  • fname의 값으로 설정 rest하고 모든 문자가 처리될 때까지 반복합니다.

확장이 패턴으로 사용되는 것을 ${fname%"$rest"}방지하기 위해 따옴표를 사용하십시오 .$rest

그런데, for file in `ls $1`피해야 합니다. 가장 확실한 이유는 파일 이름에 IFS.배쉬 트랩 1, 해야 할 일을 포함합니다.

답변4

bash문자열 분할 연산자를 사용합니다 .

s="string"
for c in $(seq 0 $((${#s}-1)));  do echo "${s:c:1}"; done

s
t
r
i
n
g

귀하에게 적용되는 스크립트는 다음과 같습니다.

#!/bin/bash
for f in *; do
    echo "Char in $f:"
    for i in $(seq 0 $((${#f}-1))); do
        echo "${f:i:1}"
    done
done

관련 정보