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 / fprend les délimiteurs successifs comme un seul. PowerShell peut mieux s'adapter.La boucle interne
for / Fn'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éfixeTTAest-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 ...