44 votes

Comment remplacer une chaîne de caractères dans un fichier à l'aide de msbuild ?

Je souhaite remplacer une chaîne de caractères telle que "how r u" dans le fichier test.xml par une chaîne de caractères "i am fine" dans un autre fichier xy.xml.en utilisant des expressions régulières dans ms build.

Je dois lire une chaîne de caractères dans un fichier (xy.xml) et la remplacer dans un autre fichier test.xml. Je vous demande donc de me fournir les étapes nécessaires à la résolution de ce problème avec un exemple.

105voto

csharptest.net Points 16556

Ce n'est plus nécessaire... vous pouvez maintenant injecter du C# dans le fichier de projet/construction...

Définissez une tâche personnalisée et des paramètres comme suit :

<UsingTask TaskName="ReplaceFileText" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
  <ParameterGroup>
    <InputFilename ParameterType="System.String" Required="true" />
    <OutputFilename ParameterType="System.String" Required="true" />
    <MatchExpression ParameterType="System.String" Required="true" />
    <ReplacementText ParameterType="System.String" Required="true" />
  </ParameterGroup>
  <Task>
    <Reference Include="System.Core" />
    <Using Namespace="System" />
    <Using Namespace="System.IO" />
    <Using Namespace="System.Text.RegularExpressions" />
    <Code Type="Fragment" Language="cs">
      <![CDATA[
            File.WriteAllText(
                OutputFilename,
                Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
                );
          ]]>
    </Code>
  </Task>
</UsingTask>

Il suffit ensuite de l'appeler comme n'importe quelle autre tâche MSBuild

<Target Name="AfterBuild">
  <ReplaceFileText 
    InputFilename="$(OutputPath)File.exe.config" 
    OutputFilename="$(OutputPath)File.exe.config" 
    MatchExpression="\$version\$" 
    ReplacementText="1.0.0.2" />
</Target>

L'exemple ci-dessus remplace "$version$" par "1.0.0.2" dans le fichier "File.exe.config" situé dans le répertoire de sortie.

0 votes

Comment passer Liste<chaîne> como paramètre pour faire des remplacements multiples ?

0 votes

Véase blogs.clariusconsulting.net/kzu/ pour une version améliorée prenant en charge les éléments et les options Regex

0 votes

J'ai dû ajouter ToolsVersion="4.0" à la balise de mon projet pour qu'il regarde dans le bon répertoire MSBuildToolsPath.

11voto

Dmitriy Ivanov Points 470

Il existe une approche très simple pour remplacer une chaîne de caractères dans un fichier :

  <Target Name="Replace" AfterTargets="CoreCompile">
      <PropertyGroup>
          <InputFile>c:\input.txt</InputFile>
          <OutputFile>c:\output.txt</OutputFile>
      </PropertyGroup>
      <WriteLinesToFile
          File="$(OutputFile)"
          Lines="$([System.IO.File]::ReadAllText($(InputFile)).Replace('from','to'))"
          Overwrite="true"
          Encoding="Unicode"/>
  </Target>

Véase https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2019 pour explorer le code C# inlinable. [System.Text.RegularExpressions.Regex] inclus dans la liste.

3 votes

Soyez prudent avec Encoding="Unicode" ! Par exemple, la valeur par défaut de app.config es Encoding="UTF-8" et il ne fonctionnera pas avec l'Unicode !

0 votes

Utilisation de Regex pour remplacer le numéro de version : <PropertyGroup> <FilePath>Properties\AssemblyInfo.cs</FilePath> </PropertyGroup> <WriteLinesToFile File="$(FilePath)" Lines="$([System.Text.RegularExpressions.Regex]::Replace($([‌​System.IO.File]::Rea‌​dAllText('$(FilePath‌​)')), 'AssemblyVersion\(&quot;\d+.\d+.\d+.\d+&quot;\)', 'AssemblyVersion(&quot;$(VersionTag)&quot;)'))" Overwrite="true" /> Désolé pour le mauvais formatage !

8voto

JamesRyan Points 21

La réponse de @csharptest.net est bien, mais il ne fonctionne pas sur DotNetCore. Je l'aurais bien ajouté en commentaire, mais je n'ai pas assez de réputation.

Sur DotNetCore, vous devez faire une mise à jour :

  • Usine de tâches vers "RoslynCodeTaskFactory"
  • Assemblage de la tâche à "$(MSBuildToolsPath) \Microsoft.Build.Tasks.Core.dll "
  • Supprimer la référence à "System.Core"
  • La cible consommatrice doit spécifier l'attribut "AfterTargets" comme étant "Build".

Tout le reste devrait être identique :

<Project Sdk="Microsoft.NET.Sdk.Web">
  ...

  <UsingTask
    TaskName="ReplaceFileText"
    TaskFactory="RoslynCodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
    <ParameterGroup>
      <InputFilename ParameterType="System.String" Required="true" />
      <OutputFilename ParameterType="System.String" Required="true" />
      <MatchExpression ParameterType="System.String" Required="true" />
      <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System"/>
      <Using Namespace="System.IO"/>
      <Using Namespace="System.Text.RegularExpressions" />
      <Code Type="Fragment" Language="cs">
        <![CDATA[  
          File.WriteAllText(
            OutputFilename,
            Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
            );
        ]]>
      </Code>
    </Task>
  </UsingTask>

  <Target Name="AfterBuildStep" AfterTargets="Build">
    <ReplaceFileText
       InputFilename="$(OutputPath)File.exe.config" 
       OutputFilename="$(OutputPath)File.exe.config" 
       MatchExpression="\$version\$" 
       ReplacementText="1.0.0.2" />
  </Target>
</Project>

4voto

Ludwo Points 3166

EDIT : Cette réponse est obsolète. Utilisez la solution ci-dessous...

Utilisez la tâche ReadLinesFromFile pour obtenir la chaîne de remplacement du fichier xy.xml. Vérifier ceci

Utilisez ensuite la valeur de xy.xml comme chaîne de remplacement pour la tâche FileUpdate. Vérifier ceci

Et mettre le tout ensemble ;)

0 votes

Je dois lire un nœud particulier avec l'attribut name object dans un fichier et remplacer ce nœud par un autre. Comment gérer ce problème ?

1 votes

Ces tâches sont issues du projet MSBuildCommunityTasks, dont l'installation peut s'avérer peu souhaitable pour une tâche aussi simple que celle-ci.

4voto

Victor Ionescu Points 854

Vous pouvez utiliser la tâche FileUpdate de MSBuild Community Tasks comme expliqué dans l'article http://geekswithblogs.net/mnf/archive/2009/07/03/msbuild-task-to-replace-content-in-text-files.aspx

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X