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
4 Réponses :
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
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.
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 ...
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!
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
@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.
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
Où rst-00
est remplacé par newline-0049
sur la ligne où était à l'origine first-004
. p>
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.
Hmmm ... Cela semble correct maintenant, testez simplement les deux dernières lignes de cet article.
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?