Chaque ligne d'un fichier donné ' a.txt ' contient le répertoire / chemin vers un autre fichier unique. Supposons que nous voulions analyser « a.txt » ligne par ligne, extraire le chemin au format chaîne, puis utiliser un outil tel que vim pour traiter le fichier à ce chemin, et ainsi de suite.
Après avoir parcouru ce fil de discussion - Lire un fichier ligne par ligne en attribuant la valeur à une variable , j'ai écrit le script suivant, disons ' open-file.sh ' sur bash (je suis nouveau)
./open-file.sh a.txt
Nous exécuterions alors le script ci-dessus comme -
#!/bin/bash while IFS='' read -r line || [[ -n "$line" ]]; do vim -c ":q" -cq $line # Just open the file and close it using :q done < "$1"
Le problème est que, bien que le chemin vers un nouveau fichier soit correctement spécifié par $ line, lorsque vim ouvre le fichier, vim continue de recevoir le texte contenu dans ' a.txt ' en tant que commande. Comment puis-je écrire un script où je peux obtenir correctement le chemin à partir de ' a.txt ', l'ouvrir à l'aide de vim, puis continuer à analyser les lignes restantes dans ' a.txt em > '?
3 Réponses :
Remplacer:
vim -c ":q" -cq "$line" </dev/tty
Avec:
vim -c ":q" -cq $line
La redirection dev / tty
indique vim
pour prendre son entrée standard du terminal. Sans cela, l'entrée standard pour vim
est "$1"
.
De plus, il est recommandé de mettre $ line code > entre guillemets pour le protéger du partage de mots , etc.
Enfin, alors que vim
est excellent pour le travail interactif, si votre objectif est un traitement entièrement automatisé de chaque fichier, vous pourriez envisager des outils tels que sed
ou awk
.
Je vérifierai les autres outils que vous avez mentionnés.
Bien que je ne sois pas sûr de votre objectif ultime, cette commande shell exécutera vim une fois par ligne dans a.txt
:
xargs -o -n1 vim -c ': q'
Comme expliqué dans les commentaires sur Lire un fichier ligne par ligne en attribuant la valeur à une variable , le problème que vous rencontrez est dû au fait que vim est un programme interactif et continue donc à lire l'entrée de $ line code >.
xargs -o
n'est pas disponible dans mon GNU findutils 4.7.0
. D'après man xargs
, il semble que -o
soit spécifique à BSD. Citation: xargs sh -c 'emacs "$ @" dev / tty' emacs
[...] Cet exemple produit le même effet que BSD - o option, mais de manière plus flexible et portable.
Intéressant et bon à connaître. J'utilise également GNU findutils 4.7.0
sur Ubuntu et la page de manuel indique que -o
a été ajouté pour une meilleure compatibilité avec BSD.
C'est étrange. La version complète est xargs (GNU findutils) 4.7.0-git
Copyright (C) 2016 [...]
. Je suis sur Ubuntu 16.04.3 LTS dans le sous-système Windows pour Linux (WSL). Lorsque j'essaie d'exécuter la commande, j'obtiens xargs: option invalide - 'o'
.
Je suis sur Ubuntu 18.04, donc je suppose qu'ils l'ont ajouté assez récemment.
Le problème était déjà mentionné dans un commentaire sous la réponse sur laquelle vous avez basé votre script.
vim
consomme stdin
qui est donné à la boucle par done . Nous pouvons observer le même comportement dans l'exemple suivant:
< "$1" xargs -d\\n -n1 vim -c :q -cq
simule un fichier avec les trois lignes
1 ,
2
et 3
. Au lieu de trois itérations silencieuses, nous n'obtenons qu'une seule itération et la sortie 2
et 3
.
stdin
n'est pas seulement passée à read
dans la tête de la boucle, mais aussi à cat
dans le corps de la boucle. Par conséquent, read
lit une ligne, la boucle est entrée, cat
lit toutes les lignes restantes, stdin
est vide, read
n'a plus rien à lire, la boucle se termine.
Vous pouvez contourner le problème en redirigeant quelque chose vers vim
, mais il existe un moyen encore meilleur. Vous n'avez pas du tout besoin de la boucle:
$ while read i; do cat; done < <(seq 3) 2 3
xargs
exécutera vim
une fois pour chaque ligne du fichier donné par $1
.
Ah oui, la réponse était dans le commentaire.