스택오버플로우의 열렬한 팬입니다. 저는 초보자이고 이 사이트에서 많은 도움을 찾았지만 이제 막혔습니다.
오늘은 아래와 같은 기능을 가지고 있습니다.
나는 새로운 줄이 쓰여질 때마다 텍스트 파일(data.txt)을 읽었습니다. 텍스트 줄에 "pets" 배열에 포함된 단어가 포함되어 있으면 해당 줄은 다른 텍스트 파일인pets.txt에 기록되지만 다른 줄은 무시됩니다.
이 기능을 어떻게 되돌릴 수 있나요?
Array(badword)를 사용하여 나쁜 단어를 차단하여 이러한 단어가 petlist.log 파일에 기록되지 않도록 하고 싶습니다.
애완동물.필터에는 다음이 포함됩니다.
pets=(
'Dog'
'Cat'
'Mouse'
'Horse'
)
badword.filter 포함
badword=(
'Stupid'
'Dumb'
'Bad'
)
script.sh에는 다음이 포함되어 있습니다.
#!/bin/bash
source /home/pi/pets.filter
source /home/pi/badword.filter
while IFS='' read -r line
do
while [ "${pets[count]}" != "" ]
do
if [ "${line/${pets[count]}}" != "$line" ] ; then
echo "$line" >> /logs/petslist.log
fi
count=$(( $count + 1 ))
done
답변1
badwords
실제로 배열인 경우성격, 다음과 같이 사용할 수 있습니다 grep -w
.
-w, --word 정규 표현식
전체 단어를 구성하는 항목이 포함된 행만 선택하십시오. 테스트에서는 일치하는 하위 문자열이 줄의 시작 부분에 있거나 단어를 만들지 않는 문자가 앞에 있어야 한다는 것입니다. 다시 말하지만, 줄 끝에 있어야 하거나 단어를 형성하지 않는 문자가 뒤에 와야 합니다. 단어를 구성하는 문자는 문자, 숫자, 밑줄입니다. -x도 지정하면 이 옵션은 적용되지 않습니다.
그래서 당신의 경우에는
# Declare some constants
readonly bad_words_list="stupid dumb bad" \
out_file="out_file" \
in_file="in_file"
# The function you want
function filter_bad_words() {
# Loop for reading line-by-line
while read -r line
do
# Loop through the list
# Notice that there are no quotes
for bad_word in ${bad_words_list[@]}
do
# Check if there is a bad word
# Options in grep: quiet, ignore case, word
if grep -qiw "$bad_word" <<< "$line"
then
# Print the line with bad word to stderr
echo "Line contains bad word: $line" 1>&2
# Exit from this loop, continue the main one
continue 2
fi
done
# Save line into the out file
# This will not be called if line contains bad word
echo "$line" >> "$out_file"
# Read from file
done < "$in_file"
}
이것이 가장 효율적인 솔루션인지는 확실하지 않지만(sed 또는 awk도 사용할 수도 있음) 적어도 이것은 작동하고 순수한 Bash입니다 grep
.
편집하다:다른 처리를 하지 않고 이러한 단어를 필터링하려는 경우 grep -o
여기에서 사용할 수도 있습니다.
# Read file into a variable
filtered="$(< "$in_file")"
# Go through each bad word
for word in ${bad_words_list[@]}
do
# Filter the word
filtered="$(grep -iv "$word" <<< "$filtered")"
done
# Save final result
echo "$filtered" > "$out_file"
답변2
당신은 일을 너무 복잡하게 만들고 있습니다.텍스트를 처리하기 위해 쉘 루프를 사용하면 안 됩니다.)
pets='Dog
Cat
Mouse
Horse'
badword='Stupid
Dumb
Bad'
grep -Fe "$pets" < input.txt > pets.txt
grep -vFe "$badword" < input.txt > input-without-badword.txt
또는 두 가지를 결합합니다.
grep -Fe "$pets" < input.txt |
grep -vFe "$badword" > pets-without-badword.txt
grep
여러 줄을 패턴(또는 F
를 사용하는 고정 문자열 -F
)으로 허용합니다. 이 경우 입력에서 해당 줄을 찾습니다.
여러 줄 문자열 대신 배열을 사용해야 하는 경우 다음과 같이 할 수 있습니다.
# fish / rc / zsh -o rcexpandparam
grep -F -e$array < input > output
# zsh
grep -F -e$^array < input > output
# mksh / bash / zsh
grep -F "${array[@]/#/-e}" < input > output
# ksh93
grep -F "${array[@]/*/-e\0}" < input > output
mksh/ksh93/zsh/bash에서는 줄바꿈을 사용하여 배열 요소를 연결할 수도 있습니다.
IFS=$'\n'
grep -Fe "${array[*]}" < input > output
또는 zsh에서:
grep -Fe ${(pj[\n])array} < input > output