4
votes

Remplacer une partie de la ligne par un texte différent d'un autre fichier ligne par ligne

J'essaie de résoudre le problème avec ça, mais je peux simplement remplacer la chaîne entière au lieu d'une partie seulement

C'est ce que j'ai jusqu'à présent:

randomText1
randomText2
randomText3
randomText4
randomText5

I veux remplacer la partie des lignes correspondant à un motif des lignes dans l'ordre à partir d'un autre fichier, j'ai jusqu'à 500 fichiers txt, avec une structure:

test1.txt, test2.txt, test3.txt ...

11111
22222
333= mock 33
55555
77777


et donc je lis le fichier un par un et à remplacer dans le premier modèle de modèle de fichier test1.txt par la première ligne du fichier mock.txt, dans le deuxième test2.txt, remplacez la ligne de modèle de simulation par la deuxième ligne du fichier mock.txt, qui a une structure comme:

mock.txt

cat mock.txt | sed -i -e '/mock/{R/dev/stdin' -e 'd;}' test{1..500}.txt


et ainsi de suite jusqu'au dernier fichier .txt du dossier


5 commentaires

1 clarification, est-ce qu'une seule ligne dans chaque fichier texte aura une chaîne mock ou il peut y en avoir plus, merci de nous le faire savoir?


ça pourrait avoir beaucoup


Ok, donc à chaque fichier suivant, vous avez besoin que la première occurrence de chaîne fictive soit remplacée par la 1ère valeur du fichier fictif? Ou il devrait continuer son compte à partir du dernier fichier?


par exemple, chaque fichier test {n} .txt a une occurrence simulée soit une ou plusieurs, donc tous les modèles simulés dans le premier fichier doivent être remplacés par la première ligne dans mock.txt, et ainsi de suite


Pourriez-vous, s'il vous plaît essayer ma solution EDIT et faites-le moi savoir, essayez-la sur 1 ou 2 fichiers une fois (fichiers de test) et voyez comment cela se passe ensuite?


4 Réponses :


1
votes

Désolé pour l'erreur précédente, veuillez réessayer ci-dessous.
Avec GNU awk v4.1.0 + (veuillez d'abord sauvegarder vos fichiers):

awk -i inplace '
    NR==FNR{re[FNR]=$0;print;next}
    FNR==1{match(FILENAME,/test([0-9]+)/, fi)}
    /mock/{gsub(/mock/,re[fi[1]])}
    1' mock.txt test{1..500}.txt

Notez que les fichiers ne peuvent pas avoir de retours chariot de terminaisons \ r \ n , s'ils ont, s'il vous plaît commenter.

Si les fichiers contiennent beaucoup de lignes, alors pour être efficace et pour le mettre en plusieurs lignes pour plus de lisibilité:

awk -i inplace 'NR==FNR{re[FNR]=$0;print;next}match(FILENAME,/test([0-9]+)/, fi){gsub("mock",re[fi[1]])}1' mock.txt test{1..500}.txt


2 commentaires

et si je veux changer toutes les occurrences de mock avec la position actuelle + 2 ou quoi que ce soit différent de la position actuelle de mock.txt, le code changerait-il beaucoup? Comme avec text1.txt, nous changerions mock en randomText3, avec text2.txt -> randomText5 et ainsi de suite


@Pursentiy Étant donné que mock.txt a des lignes redondantes, remplacez le premier re [FNR] par re [FNR-2] OU le dernier re [fi [1]] à re [fi [1] +2] ferait l'affaire.



0
votes

Cela pourrait fonctionner pour vous (GNU sed):

parallel sed -i '/mock/c\{1}' {2} :::: mockFile :::+ file{1..500}.txt

N.B. Le fichier fictif est nommé dans le script sed plutôt que comme entrée via stdin. Cela permet à sed de réinitialiser le mockFile pour chaque fichier d'entrée.

Cela remplacera toutes les instances de mock par une ligne du fichier de simulation de manière séquentielle. Cependant, si vous souhaitez lier toutes les instances de mock dans chaque fichier à sa position dans le fichier fictif, c'est-à-dire toutes les instances de mock dans le fichier1 à la ligne 1 du fichier fictif etc., utilisez:

sed -i -e '/mock/R mockFile' -e '//d' file ...


4 commentaires

Il efface toutes les lignes de mock.txt et tous les fichiers test {n} .txt sont restés les mêmes, Awk 4.1.4.


@Pursentiy Ceci est une solution sed pas un awk et le fichier fictif est en lecture seule, peut-être pourriez-vous montrer votre travail pour clarifier.


Désolé pour la confusion, je pense que @Pursentiy a commenté ma réponse, que j'ai trouvée défectueuse, j'ai donc supprimé temporairement.


@potong la question a été résolue, merci de votre aide!



0
votes

EDIT: Puisque OP dit que chaque fois que le remplacement de fichier doit commencer à partir de la toute première occurrence d'une chaîne fictive à partir d'un fichier fictif, la publication suit maintenant.

awk '
FNR==NR{
  a[FNR]=$0
  next
}
prev!=FILENAME{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}
FNR==1{
  prev=FILENAME
}
/mock/{
  $0=a[++count]
}
{
  print > "temp"
}
END{
  if(prev){
    close("temp")
    system("mv  temp " prev)
  }
}' mock.txt test[0-9].txt


2 commentaires

@Pursentiy, essayez ma solution EDIT maintenant et faites-le moi savoir? Aussi, je suggérerais d'essayer ceci avec 2 ou 3 fiels une fois qui ont l'air bien, puis ne fonctionnent que pour tous les fichiers texte.


@Pursentiy, cool, donnez-le quelque temps et lorsque vous voyez beaucoup de réponses, veuillez sélectionner l'une d'entre elles comme réponse correcte parmi toutes, bon apprentissage.



0
votes

Vous ne pouvez pas faire cela en utilisant sed en une seule étape.

Depuis info sed

sed -e '/mock/R/dev/stdin' -i test{1..500}.txt <mock.txt
sed -e '/mock/{N;s/^\(.*\)mock\(.*\)\n\(.*\)$/\1\3\2/}' -i test{1..500}.txt

Donc pour cela, vous devez faire une deuxième passe :

head -6 test-6.txt
first-001
first-002
first-003
finewline-00494
first-005
first-006

Puis

cd /tmp
seq -f first-%03g 1 20 | tee test-{1..30}.txt >/dev/null 
seq -f newline-%04g 44 244 | sed -i -e '/first-004/R/dev/stdin' test-{1..30}.txt
sed -e '/first-004/{N;s/^\(.*\)rst-00\(.*\)\n\(.*\)/\1\3\2/}' -i test-{1..30}.txt

rst-00 est remplacé par newline-0049 sur la ligne où était à l'origine first-004 . p>

A partir de là, correspondant à votre requête, mais non testé:

il y a deux passes:

'R filename'
     Queue a line of FILENAME to be read and inserted into the output
     stream at the end of the current cycle, or when the next input line
     is read.

1 commentaires

Hmmm ... Cela semble correct maintenant, testez simplement les deux dernières lignes de cet article.