Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Exxter » 21.02.2022 12:11:07

Hallo,

ich wollte mir mal ein kleines Bash-Script basteln, welches mir neue Debian-Server grundlegend einrichtet. Ich habe diese kleine Anleitung gefunden, um längeren Text in Dateien zu schreiben:

https://subinsb.com/bash-create-file-with-contents/

Ein Beispiel:

Code: Alles auswählen

cat > /root/.screenrc << ENDOFFILE
startup_message off
vbell on
vbell_msg "Hier piept's!"
hardstatus alwayslastline " %-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%< "
defscrollback 10000
screen
screen -t htop
ENDOFFILE
Das funktioniert, aber die /root/.bash_aliases nicht, es geht um dieses Script:

Code: Alles auswählen

entpacke () {
   if [ -f $1 ] ; then
       case $1 in
        *.tar.bz2)      tar xvjf $1 && cd $(basename "$1" .tar.bz2) ;;
        *.tar.gz)       tar xvzf $1 && cd $(basename "$1" .tar.gz) ;;
        *.tar.xz)       tar Jxvf $1 && cd $(basename "$1" .tar.xz) ;;
        *.bz2)          bunzip2 $1 && cd $(basename "$1" /bz2) ;;
        *.rar)          unrar x $1 && cd $(basename "$1" .rar) ;;
        *.gz)           gunzip $1 && cd $(basename "$1" .gz) ;;
        *.tar)          tar xvf $1 && cd $(basename "$1" .tar) ;;
        *.tbz2)         tar xvjf $1 && cd $(basename "$1" .tbz2) ;;
        *.tgz)          tar xvzf $1 && cd $(basename "$1" .tgz) ;;
        *.zip)          unzip $1 && cd $(basename "$1" .zip) ;;
        *.Z)            uncompress $1 && cd $(basename "$1" .Z) ;;
        *.7z)           7z e $1 && cd $(basename "$1" .7z) ;;
        *)              echo "don't know how to extract '$1'..." ;;
       esac
   else
       echo "'$1' keine gepackte Datei!"
   fi
 }
Da bleibt nur noch

Code: Alles auswählen

entpacke () {
   if [ -f  ] ; then
       case  in
        *.tar.bz2)      tar xvjf  && cd  ;;
        *.tar.gz)       tar xvzf  && cd  ;;
        *.tar.xz)       tar Jxvf  && cd  ;;
        *.bz2)          bunzip2  && cd  ;;
        *.rar)          unrar x  && cd  ;;
        *.gz)           gunzip  && cd  ;;
        *.tar)          tar xvf  && cd  ;;
        *.tbz2)         tar xvjf  && cd  ;;
        *.tgz)          tar xvzf  && cd  ;;
        *.zip)          unzip  && cd  ;;
        *.Z)            uncompress  && cd  ;;
        *.7z)           7z e  && cd  ;;
        *)              echo "don't know how to extract ''..." ;;
       esac
   else
       echo "'' keine gepackte Datei!"
   fi
 }
übrig. Gibt es eine bessere Möglichkeit, Script-Code einzufügen?

Benutzeravatar
hikaru
Moderator
Beiträge: 13896
Registriert: 09.04.2008 12:48:59

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von hikaru » 21.02.2022 12:23:29

Du musst den Delimiter quoten:

Code: Alles auswählen

cat > /root/.screenrc << "ENDOFFILE"
[..]

Exxter
Beiträge: 385
Registriert: 10.01.2003 00:15:15
Lizenz eigener Beiträge: GNU General Public License

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Exxter » 21.02.2022 12:28:27

oh man, so einfach, vielen Dank! :mrgreen:

Benutzeravatar
Livingston
Beiträge: 1813
Registriert: 04.02.2007 22:52:25
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: 127.0.0.1

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Livingston » 22.02.2022 15:52:01

Interessant, aber der Hintergrund ist mir nicht ganz klar. In der ursprünglichen Version ohne Quoting führt offensichtlich ein $ zu Problemen, mit Quoting klappt's. Aber wo ist der Zusammenhang?

EDIT: Nochmal nachgedacht: $ ist in der Bash ein Ausdruck für Zeilenende und hier auch Teil des Delimiters. Quoting sorgt dafür, dass nicht Teile sondern der komplette Delimiter als solcher betrachtet wird :?: :roll:
Richtig?
Der Hauptunterschied zwischen etwas, was möglicherweise kaputtgehen könnte und etwas, was unmöglich kaputtgehen kann, besteht darin, dass sich bei allem, was unmöglich kaputtgehen kann, falls es doch kaputtgeht, normalerweise herausstellt, dass es unmöglich zerlegt oder repariert werden kann.
Douglas Adams

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Meillo » 22.02.2022 16:18:59

Livingston hat geschrieben: ↑ zum Beitrag ↑
22.02.2022 15:52:01
Interessant, aber der Hintergrund ist mir nicht ganz klar. In der ursprünglichen Version ohne Quoting führt offensichtlich ein $ zu Problemen, mit Quoting klappt's. Aber wo ist der Zusammenhang?

EDIT: Nochmal nachgedacht: $ ist in der Bash ein Ausdruck für Zeilenende und hier auch Teil des Delimiters. Quoting sorgt dafür, dass nicht Teile sondern der komplette Delimiter als solcher betrachtet wird :?: :roll:
Richtig?
Die offizielle Erklaerung:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 hat geschrieben: 2.7.4 Here-Document

The redirection operators "<<" and "<<-" both allow redirection of subsequent lines read by the shell to the input of a command. The redirected lines are known as a "here-document".

The here-document shall be treated as a single word that begins after the next <newline> and continues until there is a line containing only the delimiter and a <newline>, with no <blank> characters in between. Then the next here-document starts, if there is one. The format is as follows:

[n]<<word
here-document
delimiter

where the optional n represents the file descriptor number. If the number is omitted, the here-document refers to standard input (file descriptor 0). It is unspecified whether the file descriptor is opened as a regular file, a special file, or a pipe. Portable applications cannot rely on the file descriptor being seekable (see XSH lseek).

If any part of word is quoted, the delimiter shall be formed by performing quote removal on word, and the here-document lines shall not be expanded. Otherwise, the delimiter shall be the word itself.

If no part of word is quoted, all lines of the here-document shall be expanded for parameter expansion, command substitution, and arithmetic expansion. In this case, the <backslash> in the input behaves as the <backslash> inside double-quotes (see Double-Quotes). However, the double-quote character ( ' )' shall not be treated specially within a here-document, except when the double-quote appears within "$()", "``", or "${}".

[...]
Zusammenfassend: Wenn der Delimiter gequotet ist, dann verhaelt sich das Heredoc wie ein String in Single-Quotes (bloss dass man Single-Quotes darin haben kann). Wenn der Delimiter nicht gequotet ist, dann verhaelt sich das Heredoc wie ein String in Double-Quotes. Indem man also den Delimiter (der ja normalerweise nur ein Wort wie ``EOF'' ist und eigentlich gar kein Quoting braucht) quotet oder nicht quotet, kann man das Quoting-Verhalten des Heredocs veraendern.

(Btw: Im Zitat ist die Formatierung des Double-Quotes kaputt. Es muesste ``... the double-quote character (") ...'' heissen.)
Use ed once in a while!

Benutzeravatar
Livingston
Beiträge: 1813
Registriert: 04.02.2007 22:52:25
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: 127.0.0.1

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Livingston » 22.02.2022 19:32:19

Uiuiui, da muss man aber tief graben, um drauf zu kommen. Ich muss mir mal wieder angewöhnen, öfters in die opengroup-Dokus reinzuschauen. Immerhin sind die DER Standard für solche Geschichten.
Danke fürs Rausklauben der Info :mrgreen:
Der Hauptunterschied zwischen etwas, was möglicherweise kaputtgehen könnte und etwas, was unmöglich kaputtgehen kann, besteht darin, dass sich bei allem, was unmöglich kaputtgehen kann, falls es doch kaputtgeht, normalerweise herausstellt, dass es unmöglich zerlegt oder repariert werden kann.
Douglas Adams

Benutzeravatar
Meillo
Moderator
Beiträge: 9224
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Langer Text mit Sonderzeichen per Bash-Script in Datei speichern

Beitrag von Meillo » 22.02.2022 23:02:47

Livingston hat geschrieben: ↑ zum Beitrag ↑
22.02.2022 19:32:19
Uiuiui, da muss man aber tief graben, um drauf zu kommen.
Die Manpage deiner bevorzugten Shell haette auch ausgereicht. ;-)

Manpage bash:

Code: Alles auswählen

       The format of here-documents is:

              <<[-]word
                      here-document
              delimiter

       No  parameter expansion, command substitution, arithmetic
       expansion, or pathname expansion is  performed  on  word.
       If  any  characters  in word are quoted, the delimiter is
       the result of quote removal on word, and the lines in the
       here-document are not expanded.  If word is unquoted, all
       lines of the here-document  are  subjected  to  parameter
       expansion,  command  substitution,  and arithmetic expan‐
       sion.  In the latter case, the character sequence  \<new‐
       line> is ignored, and \ must be used to quote the charac‐
       ters \, $, and `.
Manpage mksh:

Code: Alles auswählen

     << marker   After reading the command line containing this
                 kind of redirection (called a “here document”),
                 the shell copies lines from the command source
                 into a temporary file until a line matching
                 marker is read.  When the command is executed,
                 standard input is redirected from the temporary
                 file.  If marker contains no quoted characters,
                 the contents of the temporary file are pro‐
                 cessed as if enclosed in double quotes each
                 time the command is executed, so parameter,
                 command, and arithmetic substitutions are per‐
                 formed, along with backslash (‘\’) escapes for
                 ‘$’, ‘`’, ‘\’, and ‘\newline’, but not for ‘"’.
Manpage dash:

Code: Alles auswählen

     The following redirection is often called a
     “here-document”.

           [n]<< delimiter
                 here-doc-text ...
           delimiter

     All the text on successive lines up to the delimiter is
     saved away and made available to the command on standard
     input, or file descriptor n if it is specified.  If the
     delimiter as specified on the initial line is quoted, then
     the here-doc-text is treated literally, otherwise the text
     is subjected to parameter expansion, command substitution,
     and arithmetic expansion (as described in the section on
     “Expansions”).
Diesbezueglich gibt es grosse Einheitlichkeit, was man in der Shell ja nicht unbedingt gewohnt ist. ;-)
Use ed once in a while!

Antworten