Nie można wciąć heredoc, aby dopasować wcięcie zagnieżdżenia


62

Jeśli istnieją skrypty „Pierwszego świata”, to właśnie one.

Mam następujący kod w skrypcie, który aktualizuję:

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

Skrypt wysyła wiadomość e-mail bez problemów, ale polecenie mailx jest zagnieżdżone w instrukcji if, więc wydaje mi się, że mam dwie możliwości:

  1. Umieść EOInową linię i przerwij wzory wcięć lub
  2. Trzymaj się wcięcia, ale użyj czegoś w rodzaju echa, aby mailx wyssał mój e-mail.

Jestem otwarty na alternatywy dla heredoc, ale jeśli istnieje sposób na obejście tego, to moja preferowana składnia.

Odpowiedzi:


113

Możesz zmienić operator tutaj-doc na <<-. Następnie możesz wciąć zarówno tutaj doc, jak i separator za pomocą tabulatorów:

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

Pamiętaj, że musisz użyć tabulacji , a nie spacji, aby wciąć tutaj dokument. Oznacza to, że powyższy przykład nie będzie kopiowany (Stack Exchange zastępuje tabulatory spacjami). Wokół pierwszego EOFogranicznika nie może być żadnych cudzysłowów, w przeciwnym razie interpretacja parametrów, podstawianie poleceń i interpretacja arytmetyczna nie będą działać.


Fajnie, to naprawia problem z wcięciem, ale teraz nie rozszerza zmiennej, którą próbuję tam wstawić ( $dateLastChanged), jeśli wykonam funkcję hypen + quotes w twoim przykładzie, ale jeśli wezmę myślnik i cudzysłów i wstawię EOI na nowa linia ponownie zaczyna ją rozszerzać.
Bratchley,

1
@JelDavis: Po prostu usuń cudzysłowy, zachowaj myślnik.
choroba

5
Zmuszenie do używania kart jest bardzo denerwujące. Czy jest na to dobry sposób?
con-f-use

2
@ con-f-use: Możesz spróbować czegoś takiego cat << EOF | sed 's/^ *//'i tak dalej.
choroba

4
Albo jeszcze lepiej: cat <<- EOF | awk 'NR==1 && match($0, /^ +/){n=RLENGTH} {print substr($0, n+1)}'. To usuwa ilość poprzedzających spacji w pierwszym wierszu z każdego wiersza w dokumencie tutaj (dzięki anubhava ).
con-f-use

5

Jeśli nie potrzebujesz zastępowania poleceń i rozszerzania parametrów w dokumencie tutaj, możesz uniknąć używania tabulatorów, dodając spacje wiodące do separatora:

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

Nie mogłem jednak znaleźć sposobu na użycie tej sztuczki i utrzymanie rozszerzania parametrów.


1
Dla mnie jest to jedyna odpowiedź, która rozwiązuje problem wcięcia bez użycia spacji. shell-checkznajdzie wszelkie wcięcia, które nie pasują do spacji w cytowanym ciągu. Użyć podwójnych cudzysłowów do rozszerzenia parametrów?
Tom Hale

4

Spróbuj tego:

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

W tym przypadku nie można mieć linii o różnych wcięciach w heredoc. (Ma to znaczenie, jeśli np. Zawartość jest skryptem).
ivan_pozdeev

2

Hmm ... Wygląda na to, że możesz lepiej skorzystać z --formatargumentu tutaj, aby użyć --printfzamiast tego i po prostu przesłać los przez fajkę. Ponadto twoje polecenie if...fijest złożone - może przyjąć przekierowanie, które odziedziczą wszystkie zawarte polecenia, więc może nie musisz wcale zagnieżdżać 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

Tak, moja poprzednia wersja powiedziała, że ​​nie mam nic przeciwko części sed/ awk. Częścią mojej dzisiejszej rewizji było jej usunięcie, ponieważ nie było to istotne dla pytania. Tak czy inaczej to sześć z pół tuzina innych.
Bratchley,

@Bratchley - cholera. To ostatnie zdanie odwróci moją uwagę przez resztę dnia.
mikeserv

Co masz na myśli
Bratchley,

1
@Bratchley - wygląda jak zagadka.
mikeserv

Ha. Nie jestem pewien, z jakiego kraju pochodzisz, ale w Stanach jest to powszechne zdanie. Oznacza po prostu „inne podejście do tego samego celu”. Twoje rozwiązanie jednak omija heredoc.
Bratchley,

0

Inną metodą byłyby ciągi znaków:

    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"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.