구성 파일에 몇 줄을 추가하는 루프가 있습니다.
for i in ${H//,/ }
do
sed -i "7i\ host($i) or" $configPath/$g.conf
done
$H는 쉼표로 구분된 변수입니다(예: host1,host2,host4,host10).
다음을 반환합니다.
host(host10) or host(host4) or host(host2) or host(host1) or
하지만 내가 달성하고 싶은 것은 다음과 같습니다.
host(host10) or host(host4) or host(host2) or host(host1)
혹은 그 반대로도:
host(host1) or host(host2) or host(host4) or host(host10)
내가 이 작업을 수행하는 방법에 대한 올바른 방향을 찾는 데 도움을 줄 수 있는 사람이 있습니까?
답변1
이 문제는 대부분의 프로그래밍 언어에서 동일한 형태로 발생합니다. 어떻게든 접미사를 건너뛰는 것은 복잡할 것입니다. 나는 쉘 구문에 대해 논의하지 않을 것이며, 사람들이 일반적으로 이 문제에 접근하는 방법에 대한 의사코드 개요만 설명하겠습니다.
# get it over with at the beginning:
print a[0] (no newline)
loop from a[1] onwards:
print "or\n"
print a[i]
print "\n" #terminate the last one
이 경우에는 인덱스 테스트가 포함되지 않기 때문에(언어가 bash 및 Python과 같이 배열의 직접 반복을 지원하는 경우) 인덱스를 반복하거나 모든 요소를 반복하여(첫 번째 요소를 건너뛰는 방식으로) 작동할 수 있습니다.
0에서 시작하여 마지막 항목을 건너뛰고 루프 외부에서 처리할 수도 있지만(위 미러 참조), 마지막 항목을 건너뛰는 것은 일반적으로 더럽고 불가능할 수도 있습니다(마지막 항목을 건너뛰려면 마지막 항목임을 알아야 하지만, 첫 번째 항목은 언제든지 즉시 건너뛸 수 있습니다. 예를 들어,스트림에서 요소를 읽고 어느 것이 마지막 요소인지 미리 알 수 없는 경우 이 형식이 유일한 옵션입니다.!
또 다른 방법:
# test a loop counter
N = length of array
loop with indices:
if i==N-1:
print a[i]
else:
print a[i],"or"
이 경우 요소 수를 알아야 하며 인덱스를 지속적으로 테스트합니다. 따라서 인덱스를 반복하거나 인덱스를 개별적으로 추적해야 합니다(루프 앞에 i=0을 설정하고 루프 안에 i++를 설정).
나는 이것을 레시피로 작성하고 있으며 bash 구현은 여러분에게 맡기겠습니다.
답변2
제가 보기에는 코드를 약간만 변경하면 됩니다. 첫 번째 루프에서 비어 있는 변수에 "or"를 넣으면 됩니다.
operator=''
for i in ${H//,/ }
do
sed -i "7i\ host($i)$operator" "$configPath/$g.conf"
operator=' or'
done
답변3
일반적으로 텍스트 처리에 쉘 루프를 사용하고 싶지 않습니다. 여기서는 다음을 사용합니다 awk
.
export H
awk 'NR == 7 {
s = ENVIRON["H"]
gsub(/,/, ") or\n host(", s)
print " host(" s ")"}
{print}' file
GNU에 내부 편집 옵션이 sed
있는 것처럼 GNU (4.1.0부터)에도 동등한 옵션으로 1이 있습니다.-i
awk
-i /usr/share/awk/inplace.awk
텍스트 파일을 편집하려면 텍스트 편집기를 사용해야 한다고 생각할 수도 있습니다. 사용 vim
:
export H
vim -esc '
let @a=$H
6put a
s/.*/host(&)/
s/,/) or\rhost(/g
x' file
^사용하지 마세요-i inplace
현재 작업 디렉터리(as or)에서 확장 기능을 먼저 gawk
로드 하려고 하면 누군가가 해당 디렉터리에 악성 코드를 심었을 수 있습니다. 시스템과 함께 제공되는 확장 프로그램 의 경로 는 다를 수 있습니다. 출력을 참조하세요.inplace
inplace
inplace.awk
inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'
답변4
원래 질문에서 "sed"를 사용하는 대신 아이디어를 설명하기 위해 echo를 사용하여 더 간단한 질문을 작성했습니다. 공백으로 구분된 항목을 반복하는 대신:
- 먼저 반복 횟수를 결정하기 위해 "," 교체 뒤의 단어 수를 얻습니다.
- "()"를 사용하여 빈 문자열을 배열로 변환
- 반복 횟수
- "또는" 부분을 조건의 출력으로 가져와 변수에 넣습니다.
- 반복을 통해 배열 부분 집합
echo/sed 등도 있습니다.
#!/bin/bash H="host1,host2,host3" H2=${H//,/ } N=`echo $H2 | wc -w` H3=($H2) for ((i = 1; i <= $N; i++)) do if [ "$i" -eq "$N" ]; then OR=""; else OR=" or"; fi ITEM=${H3[$i-1]} echo "$ITEM$OR" done