J'ai les données suivantes (une liste de packages R analysés à partir d'un fichier Rmarkdown), que je veux transformer en une liste que je peux transmettre à R pour installer:
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
Je veux transformer la liste en une liste du formulaire:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
J'ai actuellement un pipeline bash qui va du fichier brut à la liste ci-dessus:
grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')' \
| sort | uniq
Je veux ajouter une étape pour transformer les nouvelles lignes en liste séparée par des virgules. J'ai essayé d'ajouter tr '\n' '","'
, ce qui échoue. J'ai également essayé un certain nombre de réponses Stack Overflow suivantes, qui échouent également:
Cela produit library(stringr)))phics)
comme résultat.
Cela produit ,%
comme résultat.
Cette réponse (avec l' -i
indicateur supprimé), produit une sortie identique à l'entrée.
'
ou"
.Réponses:
Vous pouvez ajouter des guillemets avec sed puis fusionner les lignes avec paste , comme ça:
Si vous utilisez un système basé sur GNU coreutils (c'est-à-dire Linux), vous pouvez omettre la fin
'-'
.Si vous entrez des données avec des fins de ligne de style DOS (comme suggéré par @phk), vous pouvez modifier la commande comme suit:
la source
sed 's/^\|$/"/g'|paste -sd, -
sed
seul:sed 's/.*/"&"/;:l;N;s/\n\(.*\)$/, "\1"/;tl'
paste
seul;)awk
: Alternative avec moins d'échappements shell et donc plus lisible: Production: Explication:Le
Remarqueawk
script lui-même sans tous les échappements estBEGIN { ORS="" } { print p"'"$0"'"; p=", " } END { print "\n" }
. Après avoir imprimé la première entrée, la variablep
est définie (avant cela, c'est comme une chaîne vide). Avec cette variable,p
chaque entrée (ou enawk
-speak: record ) est préfixée et imprimée en plus avec des guillemets simples autour d'elle. Laawk
variable de séparation d'enregistrement de sortieORS
n'est pas nécessaire (puisque le préfixe le fait pour vous), elle est donc définie pour être vide au niveau de l'BEGIN
ing. Oh et nous pourrions créer notre fichierEND
avec une nouvelle ligne (par exemple pour qu'il fonctionne avec d'autres outils de traitement de texte); si cela n'est pas nécessaire, la partie avecEND
et tout ce qui suit (à l'intérieur des guillemets simples) peut être supprimée.Si vous avez des fins de ligne de style Windows / DOS (
\r\n
), vous devez d'abord les convertir en style UNIX (\n
). Pour ce faire, vous pouvez mettretr -d '\015'
au début de votre pipeline:(En supposant que vous n'avez aucune utilité pour les
\r
s dans votre fichier. Hypothèse très sûre ici.)Sinon, exécutez simplement
dos2unix /path/to/input.list
une fois pour convertir le fichier sur place.la source
', 'stringr23aphics
comme sortie.print p"'"'"'"$0"'"'"'"; p=", "
—Bonnes citations, Batman!p"'\''"$0"'\''";
aurait également fonctionné (ce n'est pas POSIXy cependant), ou alternativement en utilisantbash
les chaînes de guillemets C ($''
) même justeprint p"\'"$0"\'";
(cela aurait peut-être dû doubler d'autres antislashs) mais il y a déjà l'autre méthode utilisantawk
les caractères d'échappement de.Comme le montre la réponse liée de @ don_crissti , l'option de collage est incroyablement rapide - la tuyauterie du noyau linux est plus efficace que je ne l'aurais cru si je ne l'avais pas essayé maintenant. Remarquablement, si vous pouvez être satisfait d'une seule virgule séparant vos éléments de liste plutôt que d'une virgule + espace, un pipeline de collage
est plus rapide que même un
flex
programme raisonnable (!)Mais si des performances décentes sont acceptables (et si vous n'effectuez pas de test de stress, vous ne pourrez pas mesurer les différences de facteur constant, elles sont toutes instantanées) et vous voulez à la fois de la flexibilité avec vos séparateurs et raisonnable -liner-y-ness,
est votre ticket. Oui, cela ressemble à du bruit de ligne, mais l'
H;1h;$!d;x
idiome est la bonne façon de tout aspirer, une fois que vous pouvez reconnaître que le tout est réellement facile à lire, il ests/.*/'&'/
suivi d'un slurp et d'uns/\n/, /g
.edit: à la limite de l'absurde, il est assez facile d'obtenir du flex pour battre tout le reste creux, dites simplement à stdio que vous n'avez pas besoin de la synchronisation multithread / signalhandler intégrée:
et sous stress, c'est 2-3 fois plus rapide que les pipelines de pâte, qui sont eux-mêmes au moins 5 fois plus rapides que tout le reste.
la source
(paste -d\ \'\' /dev/null /dev/null - /dev/null | paste -sd, -) <infile | cut -c2-
ferait virgule + espace @ à peu près à la même vitesse, mais comme vous l'avez noté, ce n'est pas vraiment flexible si vous avez besoin d'une chaîne de fantaisie comme séparateurflex
truc est sacrément cool mec ... c'est la première fois que je vois quelqu'un poster duflex
code sur ce site ... gros vote positif! Veuillez poster plus de ces trucs.Perl
Python one-liner:
Fonctionne de manière simple - nous redirigeons input.txt vers stdin en utilisant l'
<
opérateur du shell , lisons chaque ligne dans une liste en.strip()
supprimant les nouvelles lignes et enrepr()
créant une représentation entre guillemets de chaque ligne. La liste est ensuite jointe en une seule grande chaîne via la.join()
fonction, avec,
comme séparateurAlternativement, nous pourrions utiliser
+
pour concaténer des guillemets à chaque ligne supprimée.Perl
Essentiellement la même idée qu'auparavant: lire toutes les lignes, supprimer la nouvelle ligne, insérer des guillemets simples, tout mettre dans le tableau @cvs et imprimer les valeurs du tableau jointes par des virgules.
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scale', 'stringr'
la source
join
devraient pouvoir prendre un itérateur donc il ne devrait pas être nécessaire de matérialiser la boucle stdin à une listeJe pense que ce qui suit devrait très bien faire, en supposant que vos données soient dans le texte du fichier
Utilisons des tableaux qui ont la substitution à froid:
La sortie du script doit être la suivante:
Je crois que c'était ce que tu cherchais?
la source
bash
et bien qu'il soit sûr de supposer que quelqu'un pourrait l'utiliser (après tout AFAIK, c'est le shell le plus utilisé), il ne devrait toujours pas être pris pour acquis. En outre, il y a des pièces que vous pourriez donc améliorer le travail de soumission (en mettant des guillemets doubles). Par exemple, bien qu'il soit peu probable que les noms de packages contiennent des espaces, il est toujours préférable de citer des variables plutôt que de ne pas le faire, vous pouvez exécuter shellcheck.net dessus et voir les notes et explications qui s'y trouvent .J'ai souvent un scénario très similaire: je copie une colonne d'Excel et je veux convertir le contenu en une liste séparée par des virgules (pour une utilisation ultérieure dans une requête SQL comme
... WHERE col_name IN <comma-separated-list-here>
).Voici ce que j'ai dans mon .bashrc:
Je lance ensuite
lbl
("ligne par ligne") sur la ligne cmd qui attend l'entrée, collez le contenu du presse-papiers, appuyez sur<C-D>
et la fonction renvoie l'entrée entourée de()
. Cela ressemble à ceci:(Je ne me souviens pas pourquoi j'ai mis le dos2unix ici, probablement parce que cela cause souvent des problèmes dans la configuration de mon entreprise.)
la source
Certaines versions de sed agissent un peu différemment, mais sur mon mac, je peux tout gérer sauf le "uniq" dans sed:
Malheureusement, pour réparer la pièce unique, vous devez faire quelque chose comme:
--Paul
la source
C'est drôle que pour utiliser une liste en clair de packages R pour les installer dans R, personne n'a proposé une solution utilisant cette liste directement dans R mais se battre avec bash, perl, python, awk, sed ou quoi que ce soit pour mettre des guillemets et des virgules dans le liste. Cela n'est pas du tout nécessaire et ne résout pas non plus la façon dont la saisie et l'utilisation de la liste transformée dans R.
Vous pouvez simplement charger le fichier texte brut (dit
packages.txt
) sous forme de trame de données avec une seule variable, que vous pouvez extraire comme vecteur, directement utilisable parinstall.packages
. Donc, convertissez-le en un objet R utilisable et installez cette liste est juste:Ou sans fichier externe:
la source