Ich habe die folgenden Daten (eine Liste von R-Paketen, die aus einer Rmarkdown-Datei analysiert wurden), die ich in eine Liste umwandeln möchte, die ich zur Installation an R übergeben kann:
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
Ich möchte die Liste in eine Liste des Formulars verwandeln:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
Ich habe derzeit eine Bash-Pipeline, die von der Rohdatei zur obigen Liste führt:
grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')' \
| sort | uniq
Ich möchte einen Schritt hinzufügen, um die neuen Zeilen in die durch Kommas getrennte Liste umzuwandeln. Ich habe versucht hinzuzufügen tr '\n' '","'
, was fehlschlägt. Ich habe auch eine Reihe der folgenden Stack Overflow-Antworten ausprobiert, die ebenfalls fehlschlagen:
Dies führt library(stringr)))phics)
zu dem Ergebnis.
Dies führt ,%
zu dem Ergebnis.
Diese Antwort (mit -i
entferntem Flag) erzeugt eine Ausgabe, die mit der Eingabe identisch ist.
'
oder"
.Antworten:
Sie können mit sed Anführungszeichen hinzufügen und dann wie folgt Linien mit paste zusammenführen :
Wenn Sie ein GNU-Coreutils-basiertes System (z. B. Linux) ausführen, können Sie das Trailing weglassen
'-'
.Wenn Sie Daten mit DOS-Zeilenenden eingeben (wie von @phk vorgeschlagen), können Sie den Befehl wie folgt ändern:
quelle
sed 's/^\|$/"/g'|paste -sd, -
sed
alleine:sed 's/.*/"&"/;:l;N;s/\n\(.*\)$/, "\1"/;tl'
paste
alleine zu benutzen ;)awk
: Alternative mit weniger Shell-Flucht und daher besser lesbar: Ausgabe: Erläuterung:Das
Hinweisawk
Skript selbst ohne all das Entrinnen istBEGIN { ORS="" } { print p"'"$0"'"; p=", " } END { print "\n" }
. Nach dem Ausdruck des ersten Eintrags wird die Variablep
gesetzt (davor ist es wie eine leere Zeichenkette). Mit dieser Variablen wirdp
jeder Eintrag (oder inawk
-speak: record ) vorangestellt und zusätzlich mit einfachen Anführungszeichen versehen. Dieawk
AusgabesatztrennungsvariableORS
wird nicht benötigt (da das Präfix dies für Sie erledigt), daher ist sie zum Zeitpunkt derBEGIN
Eingabe leer . Oh und wir könnten unsere DateiEND
mit einem Zeilenumbruch versehen (zB so funktioniert es mit weiteren Textverarbeitungswerkzeugen); Sollte dies nicht benötigt werden, kann das Teil mitEND
und alles danach (innerhalb der einfachen Anführungszeichen) entfernt werden.Wenn Sie Zeilenenden im Windows / DOS-Stil (
\r\n
) haben, müssen Sie diese zuerst in den UNIX-Stil (\n
) konvertieren . Dazu können Sietr -d '\015'
am Anfang Ihrer Pipeline Folgendes einfügen:(Vorausgesetzt, Sie haben keine Verwendung für
\r
s in Ihrer Datei. Sehr sichere Annahme hier.)Alternativ können Sie
dos2unix /path/to/input.list
die Datei auch einfach einmal ausführen, um sie direkt zu konvertieren.quelle
', 'stringr23aphics
als Ausgabe.print p"'"'"'"$0"'"'"'"; p=", "
- Heilige Zitate, Batman!p"'\''"$0"'\''";
auch funktioniert hätte (es ist jedoch nicht POSIXy), oder alternativ auch nurbash
C- Anführungszeichen ($''
) zu verwendenprint p"\'"$0"\'";
(möglicherweise hätte man andere Backslashes verdoppeln müssen), aber es gibt welche bereits die andere Methode mitawk
's Zeichen entkommt.Wie die verknüpfte Antwort von @ don_crissti zeigt, ist die Einfügeoption unglaublich schnell - das Piping des Linux-Kernels ist effizienter, als ich gedacht hätte, wenn ich es nicht gerade versucht hätte. Bemerkenswerterweise, wenn Sie mit einem einzelnen Komma zufrieden sind, das Ihre Listenelemente trennt, und nicht mit einem Komma + Leerzeichen, einer Einfügepipeline
ist schneller als selbst ein vernünftiges
flex
Programm (!)Aber wenn nur eine anständige Leistung akzeptabel ist (und wenn Sie keinen Stresstest durchführen, können Sie keine konstanten Faktorunterschiede messen, sie sind alle augenblicklich) und Sie wollen sowohl Flexibilität mit Ihren als auch vernünftige Trennzeichen -Liner-y-Ness,
ist dein Ticket. Ja, es sieht aus wie Leitungsrauschen, aber die
H;1h;$!d;x
Redewendung ist der richtige Weg, um alles zu schlürfen. Sobald Sie erkennen, dass das Ganze tatsächlich leicht zu lesen ist,s/.*/'&'/
folgt ein Schlürfen und ein Schlürfens/\n/, /g
.edit: an der grenze zum absurden, es ist ziemlich einfach flex zu bekommen, um alles andere hohl zu schlagen, sag einfach stdio, dass du die eingebaute multithread / signalhandler sync nicht brauchst:
und unter stress ist das 2-3x schneller als die paste pipelines, die selbst mindestens 5x schneller sind als alles andere.
quelle
(paste -d\ \'\' /dev/null /dev/null - /dev/null | paste -sd, -) <infile | cut -c2-
würde Komma + Leerzeichen @ so ziemlich die gleiche Geschwindigkeit machen, obwohl, wie Sie bemerkt haben, es nicht wirklich flexibel ist, wenn Sie eine ausgefallene Zeichenfolge als Trennzeichen benötigenflex
Zeug ist verdammt cool, Mann ... das ist das erste Mal, dass ich jemandenflex
auf dieser Seite sehe, der eine Postleitzahl schreibt ... große positive Bewertung! Bitte poste mehr von diesem Zeug.Perl
Python Einzeiler:
Funktioniert auf einfache Weise: Wir leiten die Datei input.txt mithilfe des Shell-
<
Operators nach stdin um , lesen jede Zeile in eine Liste,.strip()
entfernen neue Zeilen undrepr()
erstellen eine in Anführungszeichen gesetzte Darstellung jeder Zeile. Die Liste wird dann über die.join()
Funktion,
als Trennzeichen zu einem großen String zusammengefügtAlternativ könnten wir verwenden,
+
um Anführungszeichen zu jeder entfernten Zeile zu verketten.Perl
Im Wesentlichen die gleiche Idee wie zuvor: Alle Zeilen lesen, Zeilenumbrüche entfernen, in einfache Anführungszeichen setzen, alles in das Array @cvs schreiben und mit Kommas verbundene Array-Werte ausdrucken.
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
quelle
join
sollten in der Lage sein, einen Iterator zu nehmen, daher sollte es nicht erforderlich sein, die stdin-Schleife in eine Liste aufzunehmenIch denke, das Folgende sollte in Ordnung sein, vorausgesetzt, Ihre Daten befinden sich im Dateitext
Verwenden wir Arrays, bei denen die Substitution kalt ist:
Die Ausgabe des Skripts sollte wie folgt aussehen:
Ich glaube, das war es, wonach du gesucht hast?
quelle
bash
und man davon ausgehen kann, dass jemand es verwendet (schließlich ist es die am häufigsten verwendete AFAIK-Shell), sollte es dennoch nicht als selbstverständlich angesehen werden. Es gibt auch Teile, die Sie besser zitieren können (doppelte Anführungszeichen). Während die Paketnamen wahrscheinlich keine Leerzeichen enthalten, ist es eine gute Konvention, Variablen in Anführungszeichen zu setzen, anstatt dies nicht zu tun. Möglicherweise möchten Sie shellcheck.net darüber ausführen und die dortigen Hinweise und Erklärungen lesen .Ich habe oft ein sehr ähnliches Szenario: Ich kopiere eine Spalte aus Excel und möchte den Inhalt in eine durch Kommas getrennte Liste konvertieren (zur späteren Verwendung in einer SQL-Abfrage wie
... WHERE col_name IN <comma-separated-list-here>
).Das habe ich in meiner .bashrc:
Ich
lbl
führe dann ("zeilenweise") die cmd-Zeile aus, die auf die Eingabe wartet, füge den Inhalt aus der Zwischenablage ein, drücke<C-D>
und die Funktion gibt die Eingabe zurück, die von umgeben ist()
. Das sieht so aus:(Ich kann mich nicht erinnern, warum ich dos2unix hierher gebracht habe, vermutlich, weil dies häufig Probleme bei der Einrichtung meines Unternehmens verursacht.)
quelle
Einige Versionen von sed verhalten sich etwas anders, aber auf meinem Mac kann ich alles außer dem "Uniq" in sed verarbeiten:
Unglücklicherweise muss man etwas tun, um das einzigartige Teil zu reparieren:
--Paul
quelle
Es ist komisch, dass niemand, der eine Klartextliste von R-Paketen verwendet, um sie in R zu installieren, eine Lösung vorschlägt, die diese Liste direkt in R verwendet, aber mit bash, perl, python, awk, sed oder was auch immer kämpft, um Anführungszeichen und Kommas in das zu setzen aufführen. Dies ist überhaupt nicht notwendig und löst außerdem nicht, wie die transformierte Liste in R eingegeben und verwendet wird.
Sie können die Klartextdatei (sagte,
packages.txt
) einfach als Datenframe mit einer einzelnen Variablen laden, die Sie als Vektor extrahieren können und die direkt von verwendet werden kanninstall.packages
. Konvertieren Sie es in ein verwendbares R-Objekt und installieren Sie diese Liste wie folgt:Oder ohne externe Datei:
quelle