Fichier contenu dans une variable Unix avec des retours à la ligne

117

J'ai un fichier texte test.txt avec le contenu suivant:

text1
text2 

Et je veux attribuer le contenu du fichier à une variable UNIX, mais quand je fais ceci:

testvar=$(cat test.txt)
echo $testvar

le résultat est:

text1 text2

au lieu de

text1
text2 

Quelqu'un peut-il me suggérer une solution pour cela?

Hugo
la source

Réponses:

185

L'affectation ne supprime pas les caractères de nouvelle ligne, c'est en echofait cela. Vous devez simplement mettre des guillemets autour de la chaîne pour conserver ces nouvelles lignes:

echo "$testvar"

Cela donnera le résultat souhaité. Consultez la transcription suivante pour une démonstration:

pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2

pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2

La raison pour laquelle les retours à la ligne sont remplacés par des espaces n'est pas entièrement liée à la echocommande, mais plutôt à une combinaison de choses.

Lorsqu'on lui donne une ligne de commande, la bashdivise en mots selon la documentation de la IFSvariable:

IFS: Le séparateur de champ interne qui est utilisé pour la division de mot après l'expansion ... la valeur par défaut est <space><tab><newline>.

Cela spécifie que, par défaut, l'un de ces trois caractères peut être utilisé pour diviser votre commande en mots individuels. Après cela, les séparateurs de mots ont disparu, il ne vous reste plus qu'une liste de mots.

Combinez cela avec la echodocumentation (une bashcommande interne), et vous verrez pourquoi les espaces sont affichés:

echo [-neE] [arg ...]: Affiche les arguments , séparés par des espaces, suivis d'une nouvelle ligne.

Lorsque vous utilisez echo "$x", cela force la xvariable entière à être un seul mot selon bash, par conséquent, il n'est pas divisé. Vous pouvez le voir avec:

pax> function count {
...>    echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1

Ici, la countfonction affiche simplement le nombre d'arguments donnés. Les variantes 1 2 3et le a b c dmontrent en action.

Ensuite, nous l'essayons avec les deux variantes de la xvariable. Celui sans guillemets montre qu'il ya quatre mots, "test", "1", "test"et "2". L'ajout des guillemets en fait un seul mot "test 1\ntest 2".

paxdiablo
la source
Les citations ... c'est ce qui me manquait! Merci!
anonymat
À noter également: les nouvelles lignes de fin seront supprimées par l'opérateur de substitution de commande lui-même: essayez-le en ligne!
Jonah
11

Cela est dû à la variable IFS (Internal Field Separator) qui contient une nouvelle ligne.

$ cat xx1
1
2

$ A=`cat xx1`
$ echo $A
1 2

$ echo "|$IFS|"
|       
|

Une solution de contournement consiste à réinitialiser IFS pour ne pas contenir la nouvelle ligne, temporairement :

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

Pour ANNULER cet horrible changement pour IFS:

IFS=$IFSBAK
DVK
la source
J'ai fait ce changement mais maintenant mes autres choses ne fonctionnent pas, dites-moi de le réinitialiser?
Pooja25
Si vous n'en avez pas besoin pour aller à une variable, un one-liner direct:echo "$(IFS=''; cat text.txt)"
Curtis Yallop
3

Juste si quelqu'un est intéressé par une autre option:

content=( $(cat test.txt) )

a=0
while [ $a -le ${#content[@]} ]
do
        echo ${content[$a]}
        a=$[a+1]
done
DerWilts
la source
3

Votre variable est correctement définie par testvar=$(cat test.txt). Pour afficher cette variable composée de caractères de nouvelle ligne, ajoutez simplement des guillemets doubles, par exemple

echo "$testvar" 

Voici l'exemple complet:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2
Kenorb
la source
0

L' envdirutilitaire fournit un moyen simple de le faire. envdirutilise des fichiers pour représenter des variables d'environnement, avec des noms de fichiers mappés sur des noms de var env et un mappage de contenu de fichier sur des valeurs de var env. Si le contenu du fichier contient des retours à la ligne, env var.

Voir https://pypi.python.org/pypi/envdir

Chris Johnson
la source