중첩의 들여 쓰기와 일치하도록 heredoc을 들여 쓸 수 없습니다


62

스크립팅에 "First World Problems"가 있다면 이것이 문제 일 것입니다.

업데이트하는 스크립트에 다음 코드가 있습니다.

if [ $diffLines -eq 1 ]; then
        dateLastChanged=$(stat --format '%y' /.bbdata | awk '{print $1" "$2}' | sed 's/\.[0-9]*//g')

        mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<EOI
        Last Change: $dateLastChanged

        This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
EOI

else
        echo "$diffLines have changed"
fi

이 스크립트는 문제없이 전자 메일을 보내지 만 mailx 명령은 if 문에 중첩되어 있으므로 두 가지 선택 사항이 남아 있습니다.

  1. 넣어 EOI새 줄에 들여 쓰기 패턴을 끊거나
  2. 들여 쓰기를 유지하지만 echox와 같은 것을 사용하여 mailx가 내 이메일을 빨아 들일 수 있도록하십시오.

heredoc에 대한 대안이 열려 있지만이를 해결할 수있는 방법이 있다면 선호하는 구문입니다.

답변:


113

here-doc 연산자를로 변경할 수 있습니다 <<-. 그런 다음 here-doc 및 구분 기호 를 탭으로 들여 쓸 수 있습니다 .

#! /bin/bash
cat <<-EOF
    indented
    EOF
echo Done

참고 사용자가 탭을 사용합니다 여기에-문서를 들여 공백이 없습니다. 즉, 위의 예제는 복사되지 않습니다 (스택 교환은 탭을 공백으로 바꿉니다). 첫 번째 EOF구분 기호 주위에 따옴표를 사용할 수 없습니다 . 그렇지 않으면 매개 변수 확장, 명령 대체 및 산술 확장이 적용되지 않습니다.


쿨, 들여 쓰기 문제를 해결하지만 이제는 $dateLastChanged예제에서 하이픈 + 따옴표를 사용 하면 변수를 확장하지 않고 ( ) 하이픈과 따옴표를 빼고 EOI를 새 줄을 다시 확장하기 시작합니다.
Bratchley

1
@JoelDavis : 따옴표를 제거하고 하이픈을 유지하십시오.
choroba

5
탭을 사용하도록 강요하는 것은 매우 성가신 일입니다. 그 주위에 좋은 방법이 있습니까?
con-f-use

2
@ con-f-use : 당신은 cat << EOF | sed 's/^ *//'등등을 시도해 볼 수 있습니다 .
choroba

4
또는 더 나은 : cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. 이렇게하면 here 문서의 모든 줄에서 첫 번째 줄의 선행 공백이 제거됩니다 ( anubhava 덕분에 ).
con-f-use

5

here-document 내에서 명령 대체 및 매개 변수 확장이 필요하지 않은 경우 구분 기호에 선행 공백을 추가하여 탭을 사용하지 않아도됩니다.

$     cat << '    EOF'
>         indented
>     EOF
        indented
$     cat << '    EOF' | sed -r 's/^ {8}//'
>         unindented
>     EOF
unindented

그러나이 트릭을 사용하고 매개 변수 확장을 유지하는 방법을 알 수 없었습니다.


1
나에게 이것은 공백을 사용하지 않고 들여 쓰기 문제를 해결하는 유일한 대답입니다. shell-check인용 된 문자열의 공백과 일치하지 않는 들여 쓰기 변경 사항을 찾습니다. 매개 변수 확장에 큰 따옴표를 사용 하시겠습니까?
Tom Hale

4

이 시도:

sed 's/^ *//' >> ~/Desktop/text.txt << EOF
    Load time-out reached and nothing to resume.
    $(date +%T) - Transmission-daemon exiting.
EOF

heredoc 내에서 다르게 들여 쓰기 된 줄을 가질 수는 없습니다. (예를 들어 내용이 스크립트 인 경우에 중요합니다.)
ivan_pozdeev

2

흠 ... 대신 --format여기 에서 인수를 사용 --printf하여 파이프를 통해 많은 것을 전달할 수있는 것 같습니다 . 또한 if...fi복합 명령입니다-포함 된 모든 명령이 상속 할 리디렉션을 취할 수 있으므로 heredoc을 전혀 중첩 할 필요가 없습니다.

if      [ "$diffLines" = 1 ]
then    stat --printf "Last Change: %.19y\n\n$(cat)\n" /.bbdata |
        mailx   -r  "Systems and Operations <sysadmin@[redacted].edu>" \
                -s  "Warning Stale BB Data" 'jadavis6@[redacted].edu'
else    echo    "$diffLines have changed"
fi      <<\STALE
This is an automated warning of stale data for the UNC-G Blackboard Snapshot process.
STALE

예, 이전 개정판에서는 sed/ awk부분을 신경 쓰지 않았다고 말했습니다 . 오늘 내 개정의 일부는 질문과 관련이 없기 때문에 그것을 꺼내는 것이 었습니다. 어느 쪽이든 그것은 다른 하나의 여섯 가지 중 하나입니다.
Bratchley

@Bratchley-젠장. 그 마지막 문장은 하루 종일 나를 산만하게 할 것입니다.
mikeserv

무슨 말이에요?
Bratchley

1
@Bratchley-수수께끼처럼 보입니다.
mikeserv

하아. 어느 나라 출신인지 확실하지 않지만 미국에서는 일반적인 문구입니다. "동일한 끝에 다른 접근"을 의미합니다. 귀하의 솔루션은 heredoc을 해결합니다.
Bratchley

0

다른 방법은 herestrings입니다.

    mail_content="Last Change: $dateLastChanged

    This is an automated warning of stale data for the UNC-G Blackboard Snapshot process."
    mailx -r "Systems and Operations <sysadmin@[redacted].edu>" -s "Warning Stale BB Data" jadavis6@[redacted].edu <<<"$mail_content"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.