Question Comment lire la ligne complète dans la boucle 'for' avec des espaces


J'essaye de courir un for boucle pour fichier et je veux afficher la ligne entière. Mais au lieu de cela, il affiche uniquement le dernier mot. Je veux la ligne complète.

for j in `cat ./file_wget_med`

do
echo $j

done

résultat après exécution:

Found.

Voici mes données:

$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.

94
2017-09-11 19:49


origine


en relation: stackoverflow.com/questions/9084257/… - Ciro Santilli 新疆改造中心 六四事件 法轮功


Réponses:


for la boucle se divise lorsqu'elle voit des espaces tels que space, tab ou newline. Donc, vous devriez utiliser IFS (Séparateur de champ interne):

IFS=$'\n'       # make newlines the only separator
for j in $(cat ./file_wget_med)    
do
    echo "$j"
done

134
2017-09-11 20:26



Et faites attention aux guillemets simples sur IFS car IFS = $ "\ n" divisera également les chaînes "nn". J'ai trouvé set IFS plus fiable que d'utiliser une syntaxe ou des fonctions plus compliquées. - erm3nda
apparemment il est conseillé de unset IFS ensuite, afin que les autres commandes ne soient pas influencées dans ce même shell. - Boris Däppen
Que fait le $ dire en IFS=$'\n'? - Ren
$ fait que les sauts de ligne fonctionnent à l'intérieur de la chaîne. Cela devrait également être fait avec local IFS=$'\n' à l'intérieur d'une fonction. - Andy Ray
@Renn c'est $'...' connu "ANSI-C citant" - αғsнιη


for les boucles sont divisées par défaut sur n'importe quel espace (espace, tabulation, nouvelle ligne); la façon la plus simple de travailler sur un ligne à la fois est d'utiliser un while read boucle au lieu de cela, qui se divise sur les nouvelles lignes:

while read i; do echo "$i"; done < ./file_wget_med

je voudrais attendre votre commande pour cracher un mot par ligne (c'est ce qui s'est passé lorsque je l'ai testé avec un fichier personnel). Si quelque chose d'autre se passe, je ne suis pas sûr de ce qui pourrait en être la cause.


67
2017-09-11 20:04



C'est aussi une bonne alternative à for i in `ls`; do echo $1; done, en redirigeant la sortie vers la commande while: ls|while read i; do echo $i; done. Cela fonctionne sur les noms de fichiers / dossiers avec des espaces, sans avoir besoin de changer les variables d'environnement. Très bonne réponse. - jishi
le temps ne gère pas très bien la première et la dernière ligne, pas plus que la boucle for avec IFS - grantbow
@jishi Comme il est principalement conçu pour l'affichage, et qu'il est sensible à la taille de la fenêtre du terminal, ls n'est pas considéré comme sûr pour une utilisation avec | (l'opérateur du tuyau). find est plus flexible en plus d'être plus sûr à cette fin. - SeldomNeedy
Ceci est une réponse géniale, je l'ai utilisé pour transformer une liste que j'avais dans les entrées PLIST pour une application IOS que je développais sur Mac OSX. J'ai remplacé l’entrée du fichier en dirigeant le clipboad en utilisant pbpaste -> pbpaste | while read t; do echo "<string>$t</string>"; done - Big Rich
ls -1 peut être utilisé avec | pour garantir une sortie non formatée par ligne - AndreyS Scherbakov


#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
    echo $fname
done <<< "$files"

Travail vérifié, pas celui que vous voulez probablement, mais ce n'est pas possible avec élégance.


16
2017-11-02 06:34



une chaîne ici! plus élégant de toutes les autres solutions IMO - Eliran Malka


Voici une légère extension à la réponse de Mitchell Currie, que j'aime bien en raison de la faible portée des effets secondaires, ce qui évite d'avoir à définir une variable:

#!/bin/bash
while read -r fname; do
    echo $fname
done <<< "`find <subdir> -name '*'`"

3
2018-06-07 15:57





Je l'écrirais comme ceci:

cat ./file_wget_med | while read -r j
do
    echo $j
done

comme il nécessite moins de changements dans le script d'origine (sauf pour la solution utilisant IFS, mais il modifie bash comportement non seulement pour cette instruction de contrôle de boucle).


0
2017-08-27 07:19