1
votes

Comment obtenir la valeur nécessaire d'un fichier texte au format très inhabituel?

J'ai une sortie qui est un fichier texte comme celui-ci ( C: \ test.txt )

@echo off
SET _c=
FOR /F "tokens=4 delims= " %%G IN (C:\test.txt) DO (
    IF DEFINED _c <nul set /p z=", "
    <nul set /p z=%%G
    SET _c=1
)

Inutile de dire que c'était un gâchis. Cependant, j'aimerais avoir la valeur de la colonne "non utilisée" qui est 111640.

Ma machine est Windows, j'ai essayé le code suivant mais cela ne m'a rien donné:

database_name                                                                                                                   |database_size     |unallocated space 
--------------------------------------------------------------------------------------------------------------------------------|------------------|------------------
web                                                                                                                     |          11120.00 MB       |11157.80 MB       

(1 sˆ—‚³‚ê‚Ü‚µ‚½)
reserved          |data              |index_size        |unused            
------------------|------------------|------------------|------------------
111360 KB         |11560 KB          |11160 KB          |111640 KB          

(1 sˆ—‚³‚ê‚Ü‚µ‚½)

Quelqu'un peut me dire comment obtenir cette valeur?


2 commentaires

Il devrait y avoir un moyen avec FINDSTR et les paramètres / r et une expression régulière quelque chose comme [0-9] * KB $


Pouvez-vous utiliser gawk ? Ce fichier est-il également terminé par des retours chariot?


8 Réponses :


2
votes

Étant donné que votre question est balisée , comment à propos de

awk -F "|" "$NF ~ /unused/{p=1} p && /[0-9]/ { print $NF; p = 0 }" messyfile.txt

J'espère que les guillemets sont appropriés pour Windows; sur U * x, j'utiliserais des guillemets simples partout.

-F définit le séparateur de champ, NF est le nombre de champs; donc $ NF examine le dernier champ de chaque ligne. Si nous voyons non utilisé dans le dernier champ, commencez à chercher un nombre. Lorsque nous voyons une ligne qui contient au moins un nombre, imprimez le dernier champ de cette ligne.

Si c'est assez proche de ce que vous voulez, j'espère que vous pouvez trouver comment le modifier, par exemple. pour supprimer le suffixe KB (indice: sub () ou split()).


3 commentaires

@Tiw Merci pour la modification. Maudit soit le clavier mobile.


Bien sûr, j'en ai repéré un mais pas l'autre.


J'apprécie vraiment votre aide. J'utiliserais aussi ceci sur ma machine Linux.



1
votes

Pourriez-vous s'il vous plaît essayer de suivre (je n'ai pas testé ceci sur l'environnement Windows).

code.awk
!flag{
  for(i=1;i<=NF;i++){
    if($i~/unused/){
      field=i
      flag=1
    }
  }
}
flag && !/^-/{
  print $field,$(field+1)
  flag=""
  exit
}'

Vous devez changer les guillemets simples en " au cas où vous l'êtes sous Windows.

Explication: Ce code recherche le numéro de champ où la chaîne non utilisée est trouvée et puis quelle que soit la ligne suivante (sans - ), il affichera ce champ spécifique et son suivant (qui contient des informations de kb etc.). Je ne suis pas le numéro de champ de codage en dur ici pour Chaîne non utilisée .

Selon le commentaire de @ MarkSetchell, nous pourrions essayer de créer un fichier code.awk et l'exécuter comme awk -f code .awk Input_file où Input_file est l'exemple de fichier.

awk '!flag{for(i=1;i<=NF;i++){if($i~/unused/){field=i;flag=1}}} flag && !/^-/{print $field,$(field+1);flag="";exit}'  Input_file

PS: Attention, je n'ai pas testé cela sur l'environnement Windows


5 commentaires

@Tiw, comme tripleee monsieur, j'ai ajouté le changement ' à " dans le cas de Windows. Puisque je n'ai pas d'environnement Windows avec moi, j'ai ajouté un avertissement juste dans mon solution maintenant + Je vérifie le terminal en ligne si je l'obtiens pour vérifier si cela fonctionne (Windows One).


Vous pouvez contourner la plupart des insuffisances de Windows en plaçant votre script awk dans un fichier séparé et en l'exécutant avec awk -f thatFile ... :-)


@MarkSetchell, cool, permettez-moi de l'essayer aussi et MERCI une TONNE de me l'avoir fait savoir, ajoutera cela dans mon message maintenant.


@MarkSetchell, a ajouté le code de type .awk maintenant, mais je ne l'ai pas testé, merci de l'avoir fait savoir. Je vais essayer de le tester. N'hésitez pas à modifier ou à me le faire savoir au cas où vous trouveriez quelque chose qui ne fonctionne pas.


Ne me forcez pas à le faire - je ne veux pas exécuter Windows! :-) La seule façon d'exécuter Windows est dans VirtualBox, alors toute cette méchanceté est dans un seul fichier VMDK que je peux facilement supprimer en une seule fois!



1
votes

Essayez cette version batch / cmd:

@echo off
for /f "usebackq" %%i in (`for /f "tokens=4 delims=|" %%j in ^(C:\test.txt^) do @echo %%j`) do (
    (echo %%i | findstr /R "[0-9][0-9]*" ) && set "thenum=%%i" && goto :outloop
)
:outloop
::echo %thenum%
::pause

La valeur est également enregistrée dans la variable thenum et peut être utilisée plus tard.

p >


0 commentaires

1
votes

Ce script de fichier .bat peut vous donner ce que vous voulez.

powershell -NoLogo -NoProfile -Command ^
    "Select-String -Path '.\test.txt' -Pattern '^\d+ .*\|\d+ .*\|\d+ .*\|(\d+).*$' |" ^
    "ForEach-Object { $_.Matches.Groups[1].Value }"


2 commentaires

Vous pouvez raccourcir avec un groupe non capturant (? :) et un quantificateur {3} => -Pattern '^ (?: \ D +. * \ | ) {3} (\ d +). * $ '| "


@LotPings - Oui, j'y ai pensé. Mais ce n'est pas beaucoup plus court et, pour moi, ce qu'il recherche est moins évident.



1
votes

Cela vous donne accès à toutes les données de votre fichier d'entrée sous le nom de cette valeur:

$ cat tst.awk
BEGIN { FS = "[[:space:]]*[|][[:space:]]*" }
{ gsub(/^[[:space:]]+|[[:space:]]+$/,"") }
prev1 ~ /^[-|]+$/ {
    split(prev2,tags)
    for (i=1; i<=NF; i++) {
        tag = tags[i]
        val = $i
        tag2val[tag] = val
    }
}
{ prev2 = prev1; prev1 = $0 }
END {
    sep = ""
    for (tag in tag2val) {
        printf "%s%s", sep, tag
        sep = ","
    }
    print ""

    sep = ""
    for (tag in tag2val) {
        printf "%s%s", sep, tag2val[tag]
        sep = ","
    }
    print ""
}

$ awk -f tst.awk file
reserved,unallocated space,database_name,data,database_size,index_size,unused
111360 KB,11157.80 MB,web,11560 KB,11120.00 MB,11160 KB,111640 KB

Si vous souhaitez une sortie CSV, ajustez simplement la section END:

$ cat tst.awk
BEGIN { FS = "[[:space:]]*[|][[:space:]]*" }
{ gsub(/^[[:space:]]+|[[:space:]]+$/,"") }
prev1 ~ /^[-|]+$/ {
    split(prev2,tags)
    for (i=1; i<=NF; i++) {
        tag = tags[i]
        val = $i
        tag2val[tag] = val
    }
}
{ prev2 = prev1; prev1 = $0 }
END {
    for (tag in tag2val) {
        val = tag2val[tag]
        printf "%s = <%s>\n", tag, val
    }
    print "---"
    print tag2val["unused"]
}

$ awk -f tst.awk file
reserved = <111360 KB>
unallocated space = <11157.80 MB>
database_name = <web>
data = <11560 KB>
database_size = <11120.00 MB>
index_size = <11160 KB>
unused = <111640 KB>
---
111640 KB


1 commentaires

Apprécier ton aide. Script incroyable.



1
votes

En regardant le contenu du fichier fourni, vous n'avez pas vraiment besoin d'un masque de recherche complexe:

@Echo Off
Set "UnUsed="
For /F "Tokens=4 Delims=|" %%A In ('Find " KB"^<"C:\test.txt" 2^>Nul'
) Do For %%B In (%%A) Do If Not Defined UnUsed Set "UnUsed=%%B"
If Defined UnUsed (Echo=%UnUsed% & Pause)


0 commentaires

1
votes

Comme dans un fichier batch, les délimiteurs consécutifs sont comptés comme celui que j'utiliserais

Sur la ligne cmd

@Echo off
for /f "tokens=7 delims=| " %%A in ('findstr "KB" C:\test.txt') do set "unused_KB=%%A"

Dans un fichier batch

for /f "tokens=7 delims=| " %A in ('findstr "KB" C:\test.txt') do @set "unused_KB=%A"


0 commentaires

1
votes

Un autre (plus simple), juste pour la collection!

@echo off

for /F "tokens=7 delims=| " %%a in (test.txt) do set "col=%%a"
echo %col%

Le jeton désiré est deux (2) lignes en dessous de celui de recherche. La ligne du jeton souhaité a deux jetons pour chacun d'eux dans la ligne de recherche. Pour cette raison, le décalage du jeton est de 3 (au lieu de 0).

Une explication détaillée de cette méthode est donnée à ce site


MODIFIER : Nouvelle méthode ajoutée

Cette méthode simple et standard fonctionne également car la valeur souhaitée est le seul septième jeton du fichier!

@echo off
setlocal

for /F "tokens=3" %%a in ('"setx /F test.txt dummyVar /R 2,3 unused /D ^|"') do set "col=%%a" & goto continue
:continue

set "col=%col:~0,-1%"
echo %col%


0 commentaires