J'ai un ensemble de fichiers qui diffèrent les uns des autres sur le contenu et le nombre de lignes. Cependant, je veux toujours incrémenter de 1 la 8e valeur de la première ligne de fichier même si les fichiers sont différents. Les valeurs sont délimitées par des points-virgules et peuvent être simplement une valeur numérique ou alphanumérique (c'est-à-dire 123 ou TBA1).
J'ai essayé d'utiliser des jetons et des boucles, mais sans succès. Je viens juste d'insérer la valeur et ensuite l'incrément "+1" que j'essayais de faire. Mes tentatives jusqu'à présent sont juste en dessous
1;12;A;23;;23;ASD;TTA3;233;HD2;233 1;232;A;b;;A
Donc, en prenant comme exemple un fichier comme ceci:
1;12;A;23;;23;ASD;TTA2;233;HD2;233 1;232;A;b;;A
Le fichier de sortie doit avoir le contenu suivant:
@Echo Off Set "SrcFile=tf.fic" Set "OutFile=ntf.text" If Not Exist "%SrcFile%" Exit /B ( For /F "UseBackQ EOL=, Tokens=1-8* Delims=;" %%A In ("%SrcFile%" ) Do For /F "Tokens=1-2* Delims=" %%I In ("%%H" ) Do Echo=%%A;%%B;%%C;%%D;%%E;%%F;%%G;%%I%%J+1;%%K)>"%OutFile%"
Remarque: certains champs peuvent être aussi vides (c'est-à-dire le cinquième champ de la première ligne) et doivent l'être également sur le fichier de sortie.
3 Réponses :
En utilisant des techniques avancées:
> Q:\Test\2019\09\12\SO_57905573.cmd 1;12;A;23;;23;ASD;TTA2;233;HD2;233 1;232;A;b;;A 1;12;A;23;;23;ASD;TTA3;233;HD2;233 1;232;A;b;;A
pour obtenir ceci:
:: Q:\Test\2019\09\12\SO_57905573.cmd @Echo Off & Setlocal EnableDelayedExpansion Set "SrcFile=tf.fic" Set "OutFile=ntf.text" If Not Exist "%SrcFile%" Exit /B Set /P "FirstLine=" <"%SrcFile%" Rem create (pseudo)array from FirstLine using self modifying code Set i=1 Set "FirstLineCol[!i!]=%FirstLine:;="&Set /a i+=1&Set "FirstLineCol[!i!]=%" rem Set FirstLine rem strip possible letters from Col[8] and retain number for /f "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%N in ("%FirstLineCol[8]%") Do Set /a "Num=%%N,Num1=%%N+1" set "FirstLineCol[8]=!FirstLineCol[8]:%Num%=%Num1%!" >"%OutFile%" ( set /p "x=!FirstLineCol[1]!"<NUL for /l %%L in (2,1,%i%) Do set /p "x=;!FirstLineCol[%%L]!"<NUL echo( more +1 "%srcFile%" ) type "%SrcFile%" echo: echo: type "%OutFile%"
J'ai pris le commentaire @LotPings (" batch n'est pas bien adapté à votre tâche car pour / f prend les délimiteurs successifs comme un seul ") comme un défi et j'ai proposé ce qui suit :
============================ Src 1;12;A;23;;23;ASD;TTA2;233 1;232;A;b;;A ============================ Out 1;12;A;23;;23;ASD;TTA3;233 1;232;A;b;;A ============================
Cela fonctionne à la fois lorsque le huitième champ est numérique:
============================ Src 1;12;A;23;;23;ASD;99;233 1;232;A;b;;A ============================ Out 1;12;A;23;;23;ASD;100;233 1;232;A;b;;A ============================
et lorsqu'il est alphanumérique:
@echo off setlocal enabledelayedexpansion Set "SrcFile=tf.fic" Set "OutFile=ntf.text" If Not Exist "%SrcFile%" Exit /B If Exist "%OutFile%" del "%OutFile%" set FIRST=Y for /f "usebackq tokens=* delims=#" %%x in ( "%SrcFile%" ) do ( set "LINE=%%x" if defined FIRST ( set "HASH=!LINE:;=;#!" for /f "usebackq tokens=1-8,* delims=#" %%a in ( '!HASH!' ) do ( set ALPHA= set NUM= for /f "tokens=1 delims=0123456789" %%y in ( "%%h" ) do set ALPHA=%%y for /f "tokens=1 delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%y in ( "%%h" ) do set NUM=%%y set /a NUM=NUM+1 set "LINE=%%a%%b%%c%%d%%e%%f%%g!ALPHA!!NUM!;%%i" set "LINE=!LINE:#=!" ) set FIRST= ) >>"%OutFile%" echo !LINE! ) echo ============================ Src type "%SrcFile%" echo ============================ Out type "%OutFile%" echo ============================
Notes / Explication
LINE
. Un traitement spécial n'a lieu que pour la première ligne (lorsque FIRST
est défini). HASH
est créé à partir de la première ligne en remplaçant tous les points-virgules (;
) par (; #
), en tournant, par exemple, aaa ;; bbb en aaa; #; # bbb
. #
est plus ou moins arbitraire, tant qu'il n'apparaîtra jamais dans un fichier réel . %% a
à %% h
) et "tout le reste" (% % i
) car il y aura toujours quelque chose entre les délimiteurs, même pour les champs vides. %% h
) en sa partie alpha (facultative) ( ALPHA
) et sa partie numérique ( NUM code >). Un peu pervers, cela repose sur le fait que les délimiteurs adjacents sont "intégrés à un": la partie alpha est délimitée par un ou plusieurs chiffres; la partie numérique est délimitée par une ou plusieurs lettres.
TTA
) suivi d'un ou plus de chiffres (par exemple 2
). Si ce n'est pas toujours le cas (par exemple, s'il peut y avoir des lettres après le (s) chiffre (s)), des ajustements doivent être effectués. delims = ABC ...
. SET / A
). #
, les délimiteurs d'origine ;
sont toujours présents, il n'est donc pas nécessaire d'ajouter. La seule exception est le huitième champ, qui, en raison de sa division en deux parties, aura perdu son point-virgule. #
restants que nous avons ajoutés. Il n'y en aura pas dans les huit premiers champs, mais %% i
(la variable "et tout le reste") peut en contenir. ; %% i
). Juste à titre de comparaison, au détriment de la lisibilité, ce script PowerShell pourrait être condensé davantage:
## Q:\Test\2019\09\12\SO_57905573.ps1 $SrcFile = ".\tf.fic" $OutFile = ".\ntf.text" $Content = (Get-Content $SrcFile) $Firstline = $Content[0] -split ';' if($Firstline[7] -match '(\d+)$'){ $Firstline[7]=$Firstline[7] -replace $Matches[1],(([int]$Matches[1])+1) } $Content[0] = $FirstLine -join ';' $Content | Set-Content $OutFile
L'index dans PowerShell est basé sur zéro.
Comme votre fichier source contient des champs vides
;;
sans prendre de précautions, le lot ne convient pas bien à votre tâche carfor / f
prend les délimiteurs successifs comme un seul. PowerShell peut mieux s'adapter.La boucle interne
for / F
n'a aucun sens puisque vous n'avez pas spécifié dedélimitations
, vous n'obtiendrez donc jamais plus d'unjetons
. Ensuite, il y a le problème des champs vides. Et vous devez spécifier comment le huitième champ est construit; le préfixeTTA
est-il toujours le même ou toujours 3 caractères? Plus vous êtes précis, moins nous avons à deviner, plus les réponses que vous obtiendrez seront adaptées ...