Как получить необходимое значение очень необычного формата текстового файла? - PullRequest
0 голосов
/ 24 января 2019

У меня есть вывод, который представляет собой текстовый файл, подобный этому (C:\test.txt)

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ˆ—‚³‚ê‚Ü‚µ‚½)

Само собой разумеется, это был беспорядок.Однако я хотел бы получить значение «неиспользуемый» столбец, равный 111640.

Моя машина - Windows, я попробовал следующий код, но он ничего не дал:

@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
)

Кто-нибудь может подсказать, как получить это значение?

Ответы [ 8 ]

0 голосов
/ 24 января 2019

Еще один (более простой), только для коллекции!

@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%

Требуемый токен на две (2) строки ниже поискового.В строке нужного токена есть два токена на каждый в строке поиска.По этой причине смещение токена равно 3 (вместо 0).

Подробное описание этого метода дано на этом сайте


РЕДАКТИРОВАТЬ : Добавлен новый метод

Этот простой и стандартный метод также работает, поскольку желаемое значение - только седьмой токен в файле!

@echo off

for /F "tokens=7 delims=| " %%a in (test.txt) do set "col=%%a"
echo %col%
0 голосов
/ 24 января 2019

При просмотре содержимого файла вам не нужна сложная маска поиска:

@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 голосов
/ 24 января 2019

Как и в пакетном файле, последовательные разделители считаются теми, которые я бы использовал

На линии cmd

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

В пакетном файле

@Echo off
for /f "tokens=7 delims=| " %%A in ('findstr "KB" C:\test.txt') do set "unused_KB=%%A"
0 голосов
/ 24 января 2019

Это дает вам доступ ко всем данным во входном файле по имени этого значения:

$ 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

Если вы хотите вывод в формате CSV, просто настройте раздел 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 {
    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
0 голосов
/ 24 января 2019

Этот скрипт .bat-файла может дать вам то, что вы хотите.

powershell -NoLogo -NoProfile -Command ^
    "Select-String -Path '.\test.txt' -Pattern '^\d+ .*\|\d+ .*\|\d+ .*\|(\d+).*$' |" ^
    "ForEach-Object { $_.Matches.Groups[1].Value }"
0 голосов
/ 24 января 2019

Попробуйте эту пакетную / 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

Значение также сохраняется в переменной thenum и может быть использовано позже.

0 голосов
/ 24 января 2019

Не могли бы вы попробовать следующее (я не проверял это в среде Windows).

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

Вам нужно изменить одинарные кавычки на ", если вы находитесь в Windows.

Объяснение: Что этот код делает, так это ищет номер поля, в котором найдена строка unused, а затем в любой следующей строке (без -) он напечатает конкретное и его следующее поле (содержащее информацию kb и т. д.). Я не жёстко кодирую номер поля здесь для unused строки.

Согласно комментарию @ MarkSetchell, мы можем попытаться создать файл code.awk и запустить его как awk -f code.awk Input_file, где Input_file - файл примера.

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

PS: Справедливое предупреждение. Я не проверял это в среде Windows

0 голосов
/ 24 января 2019

Поскольку ваш вопрос помечен , как насчет

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

Надеюсь, двойные кавычки подходят для Windows;на U * x я бы использовал одинарные кавычки.

-F устанавливает разделитель полей, NF - количество полей;поэтому $NF проверяет последнее поле в каждой строке.Если мы увидим unused в последнем поле, начните искать номер.Когда мы видим строку, которая содержит хотя бы одно число, выведите последнее поле из этой строки.

Если это достаточно близко к тому, что вы хотите, я надеюсь, что вы сможете выяснить, как настроить его, например, чтобы удалитьth KB суффикс (подсказка: sub() или split()).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...