읽기 명령은 이중 공백을 제거하고 하나만 유지합니다.

읽기 명령은 이중 공백을 제거하고 하나만 유지합니다.

로컬 컴퓨터에서 애플리케이션 로그를 수집한 다음 원격 컴퓨터에서 애플리케이션 로그를 수집하는 스크립트를 작성했습니다.

oldlogsdate수집하려는 로그의 날짜를 읽는 변수가 있습니다 .

예를 들어 입력하면 Apr 23공백이 하나뿐이므로 제대로 작동하지만 입력하면(그리고 Apr 4사이에 공백이 두 개 있으면) 공백 하나가 제거됩니다.Apr4

참고: 이는 oldlogsdate사용자의 원격 컴퓨터에도 설정되며 .bash_profile입력된 날짜는 명령을 사용하여 변경됩니다 sed.

printf "\n";read -p "Which Date Logs you want to collect = " oldlogsdate
ssh -qt [email protected] "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"

oldlogsdate="Apr 7"

이제 이것을 사용해야 하는 이유 Apr 23Apr 4명령의 일부입니다 ls.

읽기 명령에서 이중 공백을 유지하는 방법이 있습니까, 아니면 다른 더 좋은 방법이 있습니까?

여기에 이미지 설명을 입력하세요.

답변1

ssh상대방에게 보내는 명령의 일부인 명령줄에 주의하세요 .sed

ssh ... "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
        ^^^^^^^^^..................................................^^^^^^^^^^^^^^^^^^

다음은 로 표시된 두 개의 인용 문자열입니다 ^. 중간에 남아 있는 것은 다음과 같습니다.아니요변수 확장을 포함한 참조 $oldlogsdate. 언급되지 않았으므로 적용 대상이 됩니다.분사, 및 는 Apr 7두 단어가 Apr되고 7. 또한보십시오:언제 큰따옴표가 필요합니까?

이제 ssh그것들을 다시 붙일 수 있을 만큼 똑똑해졌지만 이제 원래의 공백 크기는 사라지고 공백 하나만 추가됩니다.

이는 쉘이 공백의 원래 양을 잊어버리고 echo단어를 단일 공백으로 묶는 방법과 다소 유사합니다.

$ echo hello  world
hello world

그러나 SSH를 사용하면 SSH가 해석을 위해 명령줄을 원격 측 셸에 전달하고 해당 셸에서 단어 사이의 추가 공백도 손실되기 때문에 작은따옴표가 도움이 되지 않습니다.

그래서 이것은 여전히 ​​작동하지 않습니다:

$ ssh localhost echo "hello  world"
hello world

(로컬 셸은 따옴표를 제거하고 sum 을 ssh가져와 위와 같이 작동하는 원격 셸에 전달합니다 .)echohello worldecho hello world

문자열을 그대로 유지하려면 실제로 양쪽 끝을 인용해야 합니다.

$ ssh localhost 'echo "hello  world"'
hello  world

printf ":%s\n" hello world실제로 break라는 단어의 위치를 ​​더 정확하게 표시하려면 등을 사용하는 것이 더 좋지만 결과는 비슷합니다.

큰따옴표가 가장 바깥쪽에 오도록 따옴표를 전환하여 로컬 셸에서 변수를 확장하고 원격 셸에 작은따옴표를 남겨 확장량을 최소화합니다. 다른 쪽 끝에 보내려는 큰따옴표를 백슬래시로 이스케이프해야 합니다.

$ greeting="hello  world"
$ ssh localhost "echo '$greeting'"
hello  world

변수 자체에 작은따옴표가 포함되어 있지 않으면 작동합니다. 그렇다면 상황이 더욱 악화됩니다. 다음을 참조하세요.다른 스크립트의 내용으로 사용하기 위해 변수를 이스케이프하세요

내 생각엔 명령줄@사샤의 답변귀하의 경우에는 효과가 있을 것 같습니다.

예를 들어 다음 질문도 참조하세요.ssh $host $FOO 및 ssh $host "sudo su user -c $FOO" 유형 구성에서 참조됩니다. 당면한 문제는하지만 그 대답은 "더 단순한" 경우에도 적용되는 것 같습니다.

답변2

읽기 명령은 이중 공백을 제거하고 하나만 유지합니다.

그러나 실제로는 그렇지 않습니다. 명령 read자체는 내부 공백을 변경하지 않고 그대로 둡니다(그러나 IFS공백으로 설정하지 않는 한 앞뒤 공백을 잘라냅니다. 백슬래시를 사용하지 않으면 백슬래시도 엉망이 됩니다 -r).

read myVar <<<'Apr  4'
echo "$myVar"  # will output: Apr  4

즉, 변수 주위에 큰따옴표가 없기 때문에 공백이 손실됩니다.

myVar2='Apr  4'
echo $myVar2  # will mangle spaces, please always use "$myVar2" instead

변수를 잘못 참조하면 스크립트가 예기치 않게 작동할 뿐만 아니라 잠재적인 보안 위험이 발생할 수도 있습니다.

조금더 정확한 명령은

ssh -qt [email protected] "sed -i 's/oldlogsdate=.*/oldlogsdate=\"$oldlogsdate\"/' ~/.bash_profile"

$oldlogsdate하지만 보편적이지 않고 값에 공백뿐만 아니라 아포스트로피, 슬래시, 백슬래시, 달러 기호, 느낌표도 포함될 수 있다는 점을 고려하지 않기 때문에 안전하지 않습니다 .

관련 정보