Warum unterscheidet sich echo "bar" -n von echo -n "bar"?


10

Vergleichen Sie

echo -n "bar"

mit

echo "bar" -n

Ersteres macht das, was es meiner Meinung nach tun soll (druckt "Balken" ohne Zeilenumbruch), letzteres nicht. Ist das ein Fehler oder beabsichtigt? Warum unterscheidet es sich von vielen CLI-Programmen darin, dass Sie die Optionen nicht verschieben können? Zum Beispiel tail -f /var/log/messagesist genau das gleiche wie tail /var/log/messages -f. Ich mache manchmal Letzteres, wenn ich vergesse, dass ich Ersteres wollte, weil intern die Optionen und Argumente neu angeordnet werden, normalerweise von getopt .

Update: Ja, ich habe meine Frage ursprünglich bearbeitet. Ich habe den Nerf entfernt, den Sie im Verlauf anzeigen müssen, damit einige der Antworten sinnvoll sind.


3
Von dem, was ich sehe, ist der Unterschied ist sofort offensichtlich. echo -n "bar"gibt "bar", während echo "bar" -ngibt "bar -n"
phunehehe

Antworten:


18

Wie die meisten anderen beobachtet haben, wird "-n" wörtlich interpretiert, wenn es irgendwo anders als unmittelbar nach dem echoBefehl platziert wird.

In der Vergangenheit waren alle UNIX-Dienstprogramme so - sie suchten erst unmittelbar nach dem Befehlsnamen nach Optionen. Es war wahrscheinlich entweder BSD oder GNU, die Pionierarbeit für den flexibleren Stil geleistet haben (obwohl ich mich irren könnte), da POSIX bereits jetzt den alten Weg als korrekt spezifiziert (siehe Richtlinie 9 und auch man 3 getoptauf einem Linux-System). Obwohl die meisten Linux-Dienstprogramme heutzutage den neuen Stil verwenden, gibt es einige Holdouts wie echo.

EchoIn Bezug auf Standards ist dies insofern ein Chaos, als zum Zeitpunkt der Gründung von POSIX mindestens zwei grundlegend widersprüchliche Versionen im Spiel waren. Auf der einen Seite haben Sie den SYSV-Stil, der Backslash-Escape-Zeichen interpretiert, ansonsten aber seine Argumente wörtlich behandelt und keine Optionen akzeptiert. Auf der anderen Seite haben Sie einen BSD-Stil, der eine Initiale -nals Sonderfall behandelt und absolut alles andere buchstäblich ausgibt. Und da dies echoso praktisch ist, haben Sie Tausende von Shell-Skripten, die von dem einen oder anderen Verhalten abhängen:

echo Usage: my_awesome_script '[-a]' '[-b]' '[-c]' '[-n]'
echo -a does a thing.
echo -b does something else.
echo -c makes sure -a works right.
echo -- DON\'T USE -n -- it\'s not finished! --

Aufgrund der Semantik "Alles wörtlich behandeln" ist es unmöglich, eine neue Option hinzuzufügen, echoohne die Dinge zu beschädigen. Wenn GNU das flexible Optionsschema verwenden würde, würde die Hölle losbrechen.

Verwenden Sieprintfecho für eine optimale Kompatibilität zwischen Bourne-Shell-Implementierungen übrigens eher als .

AKTUALISIERT , um zu erklären, warum echoinsbesondere keine flexiblen Optionen verwendet werden.


upvote, da du der einzige bist, der erwähnt, dass dies das erwartete getopt-Verhalten ist.
Geoffrey Bachelet

@jander warum ist echo ein "holdout"? Ich denke, es ist ein Gnu Coreutil?
Xenoterracide

@xeno: Ich habe meine Antwort aktualisiert. Grundsätzlich wollte GNU nichts kaputt machen.
Jander

1
Optionen nach der ersten nicht-Option zu akzeptieren ist spezifisch für GNU Utilities und Programm mit GNU libc ‚s getopt Einrichtungen. Der Benutzer kann immer ein abwärtskompatibles Verhalten erhalten, indem er die Umgebungsvariable festlegt POSIXLY_CORRECT.
Gilles 'SO - hör auf böse zu sein'

1
Für den speziellen Fall von echogibt es auch Implementierungen, die -eoder -Eals Optionen erkennen. Beginnen Sie aus Gründen der Portabilität nicht mit einem -oder verwenden Sie so etwas wie printf %s -e.
Gilles 'SO - hör auf böse zu sein'

9

Die anderen Antworten kommen zu dem Punkt, an dem Sie auf der Manpage nachsehen können, dass -n Teil der zu hallenden Zeichenfolge wird. Ich möchte jedoch nur darauf hinweisen, dass es einfach ist, dies ohne die md5sum zu untersuchen, und das, was vor sich geht, etwas weniger kryptisch macht.

[11:07:44][dasonk@Chloe:~]: echo -n "bar"
bar[11:07:48][dasonk@Chloe:~]: echo "bar" -n
bar -n

3
+1 genau. Wenn eine Pipeline nicht das tut, was Sie erwarten, testen Sie jedes Teil separat.
Mikel

6

Wow, alle Erklärungen sind lang.

So einfach ist das:

-n ist eine Option, wenn sie vor der Zeichenfolge angezeigt wird, andernfalls ist es nur eine weitere Zeichenfolge, die wiedergegeben werden soll.

Entfernen Sie das | md5sum und Sie werden sehen, dass die Ausgabe anders ist.


5

Nach einfacher Inspektion ist dies kein Fehler ...

echo "bar" -n | md5sum

a3f8efa5dd10e90aee0963052e3650a1

Probieren Sie diesen Befehl selbst aus:

echo "bar -n" | md5sum

Sie werden feststellen, dass der resultierende md5 ist

a3f8efa5dd10e90aee0963052e3650a1

Sie haben gerade die Verwendung von -n im Echo verwechselt.

In Ihrem ersten Beispielcode

echo -n "bar" | md5sum

-n wird verwendet, um zu sagen, dass nach diesem Echo KEINE neue Zeile eingefügt werden soll.

Ihre zweite Probe

echo "bar" -n | md5sum

behandelt -n als wörtlichen Text.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.