소개
이 튜토리얼은 셸 프로그래밍의 기본 기술인 Bash 배열에서 일치하는 요소를 제거하는 과정을 안내합니다. 배열을 사용하면 단일 변수에 여러 값을 저장할 수 있으므로 스크립트에서 데이터 컬렉션을 관리하는 데 필수적입니다.
이 튜토리얼을 마치면 특정 기준과 일치하는 특정 요소를 제거하는 데 중점을 두고 Bash 배열을 효과적으로 생성, 조작 및 수정하는 방법을 이해하게 됩니다. 이러한 기술은 다양한 자동화 작업에 더 효율적이고 강력한 Bash 스크립트를 작성하는 데 도움이 될 것입니다.
Bash 배열 생성 및 작업
배열에서 요소를 제거하는 방법을 배우기 전에 먼저 Bash 배열을 생성하고 작업하는 방법을 이해해 보겠습니다.
첫 번째 배열 생성
LabEx 환경에서 터미널을 엽니다. 먼저 간단한 과일 배열을 만들어 보겠습니다.
fruits=("apple" "banana" "cherry" "orange" "apple")
이 명령은 "fruits"라는 이름의 배열을 생성하며, 5 개의 요소를 포함합니다. "apple"이 두 번 나타나는 것을 주목하세요. 이는 나중에 일치하는 요소를 제거하는 연습을 할 때 유용합니다.
배열 요소 표시
배열의 모든 요소를 보려면 다음을 사용합니다.
echo "${fruits[@]}"
모든 요소를 표시하는 출력을 볼 수 있습니다.
apple banana cherry orange apple
특정 요소를 표시하려면 해당 인덱스를 지정할 수 있습니다 (Bash 에서 배열 인덱스는 0 부터 시작하는 것을 기억하세요).
echo "${fruits[0]}" ## 첫 번째 요소 표시: apple
echo "${fruits[1]}" ## 두 번째 요소 표시: banana
배열 길이 확인
배열에 몇 개의 요소가 있는지 확인하려면 다음을 사용합니다.
echo "${#fruits[@]}"
이것은 5를 출력해야 합니다. 이는 과일 배열의 총 요소 수입니다.
배열에 요소 추가
+= 연산자를 사용하여 기존 배열에 새 요소를 추가할 수 있습니다.
fruits+=("grape")
echo "${fruits[@]}"
이제 출력에는 "grape"가 마지막에 포함되어야 합니다.
apple banana cherry orange apple grape
작업 파일 생성
배열 작업을 연습할 파일을 만들어 보겠습니다. WebIDE 에서 파일 탐색기 패널의 "New File" 아이콘을 클릭하여 /home/labex/project 디렉토리에 array_operations.sh라는 새 파일을 만듭니다.
다음 코드를 파일에 추가합니다.
#!/bin/bash
## Define our fruits array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
## Display all elements
echo "All fruits in the array:"
echo "${fruits[@]}"
## Display the number of elements
echo "Number of fruits: ${#fruits[@]}"
## Display the first element
echo "First fruit: ${fruits[0]}"
파일을 저장하고 (Ctrl+S 또는 메뉴 사용) 실행 가능하게 만듭니다.
chmod +x /home/labex/project/array_operations.sh
이제 스크립트를 실행합니다.
./array_operations.sh
배열 요소, 개수 및 첫 번째 요소를 표시하는 출력을 볼 수 있습니다.
All fruits in the array:
apple banana cherry orange apple grape
Number of fruits: 6
First fruit: apple
축하합니다! 첫 번째 Bash 배열을 만들고 기본 작업을 수행했습니다. 다음 단계에서는 배열에서 특정 요소를 제거하는 방법을 배우겠습니다.
for 루프와 unset 을 사용하여 요소 제거
이제 Bash 배열의 기본 사항을 이해했으므로 배열에서 일치하는 요소를 제거하는 방법을 살펴보겠습니다. for 루프와 unset 명령을 사용하는 가장 간단한 방법부터 시작합니다.
unset 명령 이해
Bash 의 unset 명령을 사용하면 인덱스를 지정하여 배열에서 요소를 제거할 수 있습니다. 예를 들어, fruits 배열의 첫 번째 요소를 제거하려면 다음과 같이 합니다.
unset fruits[0]
echo "${fruits[@]}"
이것을 실행하면 다음과 같이 출력됩니다.
banana cherry orange apple grape
첫 번째 "apple"이 제거되었지만 배열 인덱스는 자동으로 재정렬되지 않습니다. 즉, 요소를 제거한 후 배열에 인덱스 시퀀스에 "갭"이 있을 수 있습니다.
for 루프를 사용하여 일치하는 요소 제거
과일 배열에서 "apple"의 모든 발생을 제거하는 새 스크립트를 만들어 보겠습니다. WebIDE 에서 /home/labex/project 디렉토리에 remove_elements.sh라는 새 파일을 만듭니다.
#!/bin/bash
## Define our fruits array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
echo "Original array: ${fruits[@]}"
## Loop through the array indices in reverse order
for ((i = ${#fruits[@]} - 1; i >= 0; i--)); do
if [ "${fruits[$i]}" == "apple" ]; then
unset "fruits[$i]"
fi
done
## Print the modified array
echo "Array after removing 'apple': ${fruits[@]}"
## Reindex the array to remove gaps (optional)
fruits=("${fruits[@]}")
echo "Array after reindexing: ${fruits[@]}"
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/remove_elements.sh
스크립트를 실행합니다.
./remove_elements.sh
다음과 유사한 출력을 볼 수 있습니다.
Original array: apple banana cherry orange apple grape
Array after removing 'apple': banana cherry orange grape
Array after reindexing: banana cherry orange grape
코드 이해
스크립트가 수행하는 작업을 살펴보겠습니다.
- 두 개의 "apple" 인스턴스를 포함하여 다양한 과일 이름이 있는
fruits라는 배열을 정의했습니다. - 배열 인덱스를 역순으로 반복했습니다 (요소를 제거할 때 인덱스 이동 문제를 방지하기 위해).
- 각 요소에 대해 "apple"과 같은지 확인하고 그렇다면 제거했습니다.
- 일치하는 모든 요소를 제거한 후 인덱스 시퀀스에 있는 갭을 제거하기 위해 배열을 다시 인덱싱했습니다.
배열을 역순으로 반복했음을 주목하세요. 요소를 제거할 때 이 점이 중요합니다. 정방향으로 반복하는 동안 요소를 제거하면 나머지 요소의 인덱스가 이동하여 일부 요소를 건너뛸 수 있습니다.
다른 값으로 실험
사용자가 지정한 모든 과일을 제거할 수 있도록 스크립트를 수정해 보겠습니다. remove_elements.sh 파일을 다음과 같이 편집합니다.
#!/bin/bash
## Define our fruits array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
## If no argument provided, default to removing "apple"
fruit_to_remove=${1:-"apple"}
echo "Original array: ${fruits[@]}"
echo "Removing: $fruit_to_remove"
## Loop through the array indices in reverse order
for ((i = ${#fruits[@]} - 1; i >= 0; i--)); do
if [ "${fruits[$i]}" == "$fruit_to_remove" ]; then
unset "fruits[$i]"
fi
done
## Print the modified array
echo "Array after removing '$fruit_to_remove': ${fruits[@]}"
## Reindex the array to remove gaps
fruits=("${fruits[@]}")
echo "Array after reindexing: ${fruits[@]}"
파일을 저장하고 다른 인수를 사용하여 실행합니다.
./remove_elements.sh banana
"banana"가 제거되었음을 보여주는 출력을 볼 수 있습니다.
Original array: apple banana cherry orange apple grape
Removing: banana
Array after removing 'banana': apple cherry orange apple grape
Array after reindexing: apple cherry orange apple grape
배열의 다른 과일 이름으로 시도해 보세요.
./remove_elements.sh orange
잘하셨습니다! for 루프와 unset 명령을 사용하여 Bash 배열에서 일치하는 요소를 제거하는 방법을 배웠습니다. 다음 단계에서는 배열에서 요소를 제거하는 다른 방법을 살펴보겠습니다.
요소 제거를 위한 대체 방법
for 루프와 unset 은 배열에서 요소를 제거하는 일반적인 방법이지만, Bash 는 특정 상황에서 더 간결하거나 효율적일 수 있는 다른 방법을 제공합니다. 두 가지 대체 방법을 살펴보겠습니다.
방법 1: 필터링된 요소로 새 배열 생성
기존 배열에서 요소를 제거하는 대신, 유지하려는 요소만 포함하는 새 배열을 만들 수 있습니다. 이 방법은 요소를 제거한 후 배열을 다시 인덱싱할 필요가 없습니다.
/home/labex/project 디렉토리에 filter_array.sh라는 새 파일을 만듭니다.
#!/bin/bash
## Define our fruits array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
## If no argument provided, default to removing "apple"
fruit_to_remove=${1:-"apple"}
echo "Original array: ${fruits[@]}"
echo "Removing: $fruit_to_remove"
## Create a new array without the matching elements
declare -a filtered_fruits
for fruit in "${fruits[@]}"; do
if [ "$fruit" != "$fruit_to_remove" ]; then
filtered_fruits+=("$fruit")
fi
done
## Print the filtered array
echo "Array after removing '$fruit_to_remove': ${filtered_fruits[@]}"
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/filter_array.sh
스크립트를 실행합니다.
./filter_array.sh
다음과 같은 출력을 볼 수 있습니다.
Original array: apple banana cherry orange apple grape
Removing: apple
Array after removing 'apple': banana cherry orange grape
방법 2: 배열 대체 패턴 사용
Bash 는 배열을 필터링하는 데 사용할 수 있는 강력한 매개변수 확장 구문을 제공합니다. 새 스크립트에서 이 방법을 구현해 보겠습니다.
/home/labex/project 디렉토리에 pattern_remove.sh라는 파일을 만듭니다.
#!/bin/bash
## Define our fruits array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
## If no argument provided, default to removing "apple"
fruit_to_remove=${1:-"apple"}
echo "Original array: ${fruits[@]}"
echo "Removing: $fruit_to_remove"
## Create a temporary array to store valid indices
declare -a indices=()
for i in "${!fruits[@]}"; do
if [ "${fruits[$i]}" != "$fruit_to_remove" ]; then
indices+=("$i")
fi
done
## Create the filtered array using the valid indices
declare -a filtered_fruits=()
for i in "${indices[@]}"; do
filtered_fruits+=("${fruits[$i]}")
done
## Print the filtered array
echo "Array after removing '$fruit_to_remove': ${filtered_fruits[@]}"
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/pattern_remove.sh
스크립트를 실행합니다.
./pattern_remove.sh grape
"grape"가 제거된 출력을 볼 수 있습니다.
Original array: apple banana cherry orange apple grape
Removing: grape
Array after removing 'grape': apple banana cherry orange apple
방법 비교
세 가지 방법을 모두 비교하는 요약 스크립트를 만들어 보겠습니다. /home/labex/project 디렉토리에 compare_methods.sh라는 파일을 만듭니다.
#!/bin/bash
## Define our test array
fruits=("apple" "banana" "cherry" "orange" "apple" "grape")
fruit_to_remove=${1:-"apple"}
echo "Original array: ${fruits[@]}"
echo "Removing: $fruit_to_remove"
echo ""
## Method 1: Using for loop and unset
echo "Method 1: Using for loop and unset"
declare -a fruits_copy=("${fruits[@]}")
for ((i = ${#fruits_copy[@]} - 1; i >= 0; i--)); do
if [ "${fruits_copy[$i]}" == "$fruit_to_remove" ]; then
unset "fruits_copy[$i]"
fi
done
fruits_copy=("${fruits_copy[@]}")
echo "Result: ${fruits_copy[@]}"
echo ""
## Method 2: Creating a new filtered array
echo "Method 2: Creating a new filtered array"
declare -a filtered_fruits=()
for fruit in "${fruits[@]}"; do
if [ "$fruit" != "$fruit_to_remove" ]; then
filtered_fruits+=("$fruit")
fi
done
echo "Result: ${filtered_fruits[@]}"
echo ""
## Method 3: Using array indices
echo "Method 3: Using array indices"
declare -a indices_filtered=()
for i in "${!fruits[@]}"; do
if [ "${fruits[$i]}" != "$fruit_to_remove" ]; then
indices_filtered+=("${fruits[$i]}")
fi
done
echo "Result: ${indices_filtered[@]}"
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/compare_methods.sh
제거할 다른 과일로 스크립트를 실행합니다.
./compare_methods.sh banana
세 가지 방법을 모두 비교하는 것을 볼 수 있습니다.
Original array: apple banana cherry orange apple grape
Removing: banana
Method 1: Using for loop and unset
Result: apple cherry orange apple grape
Method 2: Creating a new filtered array
Result: apple cherry orange apple grape
Method 3: Using array indices
Result: apple cherry orange apple grape
세 가지 방법 모두 동일한 목표를 달성하지만 각각 장점이 있습니다.
- 방법 1 (for 루프와 unset 사용) 은 원래 배열을 제자리에서 수정합니다.
- 방법 2 (새 배열 생성) 는 종종 더 명확하며 인덱스 이동 문제를 방지합니다.
- 방법 3 (배열 인덱스 사용) 은 원래 배열을 보존해야 할 때 유용할 수 있습니다.
특정 사용 사례 및 코딩 스타일에 가장 적합한 방법을 선택하십시오.
실습: 파일 정리 스크립트 구축
이제 Bash 배열에서 요소를 제거하는 다양한 방법을 이해했으므로 이 지식을 실제 상황에 적용해 보겠습니다. 특정 파일 형식을 필터링하여 디렉토리를 정리하는 데 도움이 되는 스크립트를 만들 것입니다.
파일 정리 과제
다양한 파일 형식 (텍스트 파일, 이미지, 문서) 이 포함된 디렉토리가 있고 특정 파일 형식을 선택적으로 제거하려는 경우를 상상해 보십시오. Bash 배열을 사용하여 이러한 파일을 관리하고 배열 필터링에 대한 지식을 적용합니다.
1 단계: 샘플 파일로 테스트 디렉토리 설정
먼저, 몇 가지 샘플 파일로 테스트 디렉토리를 만들어 보겠습니다. 터미널을 열고 다음을 실행합니다.
mkdir -p /home/labex/project/test_files
cd /home/labex/project/test_files
## Create some sample files
touch file1.txt file2.txt document1.pdf document2.pdf image1.jpg image2.jpg script.sh config.yaml
파일이 생성되었는지 확인합니다.
ls -la
방금 만든 샘플 파일 목록이 표시됩니다.
2 단계: 파일 정리 스크립트 만들기
이제 배열 연산을 사용하여 파일을 필터링하는 스크립트를 만들어 보겠습니다. /home/labex/project 디렉토리에 cleanup_files.sh라는 새 파일을 만듭니다.
#!/bin/bash
## Directory to scan
target_dir=${1:-"/home/labex/project/test_files"}
## File extension to filter out
extension_to_remove=${2:-"txt"}
echo "Scanning directory: $target_dir"
echo "Will remove files with extension: $extension_to_remove"
## Change to the target directory
cd "$target_dir" || {
echo "Directory not found!"
exit 1
}
## Get all files in the directory
all_files=(*)
echo "All files: ${all_files[@]}"
## Create an array to store files to keep
declare -a files_to_keep=()
## Filter out files with the specified extension
for file in "${all_files[@]}"; do
if [[ "$file" != *.$extension_to_remove ]]; then
files_to_keep+=("$file")
fi
done
echo "Files to keep: ${files_to_keep[@]}"
## Create an array of files to remove
declare -a files_to_remove=()
for file in "${all_files[@]}"; do
if [[ "$file" == *.$extension_to_remove ]]; then
files_to_remove+=("$file")
fi
done
echo "Files that would be removed: ${files_to_remove[@]}"
## Ask for confirmation before removing
echo
echo "This script is in simulation mode and won't actually delete any files."
echo "In a real scenario, you would ask for confirmation before deletion:"
echo "read -p 'Are you sure you want to remove these files? (y/n): ' confirm"
echo "if [ \"\$confirm\" == \"y\" ]; then rm \"\${files_to_remove[@]}\"; fi"
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/cleanup_files.sh
3 단계: 파일 정리 스크립트 실행
이제 스크립트를 실행하여 파일이 식별되고 필터링되는 방식을 확인해 보겠습니다.
./cleanup_files.sh
이렇게 하면 제거될 파일 (.txt 확장자를 가진 파일) 을 나타내는 출력이 표시됩니다.
다른 파일 확장자로 시도해 보세요.
./cleanup_files.sh /home/labex/project/test_files pdf
이렇게 하면 .pdf 확장자를 가진 파일이 제거될 파일로 표시됩니다.
4 단계: 배치 처리를 사용하여 스크립트 향상
한 번에 여러 파일 확장을 처리하도록 스크립트를 향상시켜 보겠습니다. /home/labex/project 디렉토리에 advanced_cleanup.sh라는 새 파일을 만듭니다.
#!/bin/bash
## Directory to scan
target_dir=${1:-"/home/labex/project/test_files"}
## Default extensions to remove
extensions=("txt" "pdf")
## Override default extensions if provided as arguments
if [ $## -gt 1 ]; then
extensions=("${@:2}")
fi
echo "Scanning directory: $target_dir"
echo "Will filter files with these extensions: ${extensions[@]}"
## Change to the target directory
cd "$target_dir" || {
echo "Directory not found!"
exit 1
}
## Get all files in the directory
all_files=(*)
echo "All files: ${all_files[@]}"
## Create an array to store files to keep
declare -a files_to_keep=()
## Create an array to store files to remove
declare -a files_to_remove=()
## Process each file
for file in "${all_files[@]}"; do
## Extract the file extension
file_ext="${file##*.}"
## Check if the file extension is in our list
should_remove=false
for ext in "${extensions[@]}"; do
if [ "$file_ext" == "$ext" ]; then
should_remove=true
break
fi
done
## Add to appropriate array based on whether it should be removed
if [ "$should_remove" == true ]; then
files_to_remove+=("$file")
else
files_to_keep+=("$file")
fi
done
echo "Files to keep: ${files_to_keep[@]}"
echo "Files that would be removed: ${files_to_remove[@]}"
echo
echo "This script is in simulation mode and won't actually delete any files."
echo "In a real scenario, you would ask for confirmation before deletion."
파일을 저장하고 실행 가능하게 만듭니다.
chmod +x /home/labex/project/advanced_cleanup.sh
확장자의 다른 조합으로 고급 스크립트를 실행합니다.
./advanced_cleanup.sh /home/labex/project/test_files txt jpg
이렇게 하면 제거할 .txt 및 .jpg 파일이 모두 식별됩니다.
우리가 한 일 이해하기
이 실습에서 우리는 다음을 수행했습니다.
- 다양한 파일 형식을 사용하여 테스트 환경을 만들었습니다.
- 배열 필터링을 사용하여 특정 확장자를 가진 파일을 식별하는 기본 스크립트를 구축했습니다.
- 여러 파일 확장을 처리하도록 스크립트를 향상시켰습니다.
- 실제 시나리오에서 Bash 배열을 사용하는 방법을 시연했습니다.
이 예제는 우리가 배운 배열 조작 기술을 파일 관리 및 정리 작업과 같은 실제 문제에 어떻게 적용할 수 있는지 보여줍니다. 배열을 필터링하는 기능은 Bash 스크립팅 도구 상자에서 강력한 도구입니다.
요약
Bash 배열에서 일치하는 요소를 제거하는 이 튜토리얼을 완료하신 것을 축하드립니다. 쉘 스크립팅 기능을 향상시킬 수 있는 귀중한 기술을 습득했습니다.
- Bash 배열 생성 및 조작
- for 루프 및 unset 메서드를 사용하여 배열에서 요소 제거
- 배열 요소를 필터링하기 위한 대체 방법
- 실제 파일 관리 작업에 배열 필터링 기술 적용
이러한 기술은 Bash 스크립팅 도구 상자의 필수적인 부분이며 다양한 자동화 작업, 데이터 처리 작업 및 시스템 관리 작업에 적용할 수 있습니다.
이 튜토리얼의 몇 가지 주요 내용:
- Bash 배열은 데이터 모음을 저장하고 처리하는 편리한 방법을 제공합니다.
- 배열에서 요소를 제거할 때는 인덱스 이동에 유의하십시오.
- 배열을 필터링하는 다양한 방법은 사용 사례에 따라 서로 다른 장점이 있습니다.
- 배열 조작 기술은 파일 관리와 같은 실제 문제를 해결하는 데 적용할 수 있습니다.
Bash 스크립팅 여정을 계속 진행하면서 이러한 배열 조작 기술은 더 효율적이고 강력한 스크립트를 작성하는 데 매우 유용할 것입니다. Bash 배열 작업에 대한 지식을 새로 고쳐야 할 때마다 주저하지 말고 이 튜토리얼을 참조하십시오.



