如何在txt文件中保存状态更改

问题描述 投票:0回答:1

恐怕我无法想象如何编写正确的批处理脚本来解决以下任务。 你能帮忙吗?

我有一个文本文件“2024-04-29_22-23log.txt”,其中每一行(第一行除外)以 OPEN 或 CLOSE 开头,后跟时间戳。 为了突出显示状态更改,我只想保留该单词与上一行不同的行。 但我想保留前两行和最后一行。

示例: 1 2024-04-29_22-23 2 关闭 22:23 3 关闭 22:24 4 开放时间 22:25 5 开放时间 22:26 6 开盘 22:27 7 关闭 22:28 8 关闭 22:29 9 关闭 22:30

应该得到: 1 2024-04-29_22-23 2 关闭 22:23 3 开放时间 22:25 4 关闭 22:28 5 22:30 关闭

感谢您的帮助。

以下仅适用于按字母顺序排列的文件名,并且忘记了最后一行!

@echo off
setlocal enabledelayedexpansion

set /p "inputFile=Enter file name : "
set "outputFile=!inputFile!_filtered.txt"

rem Copy the first line to the output file
set "lineNum=0"
for /f "usebackq delims=" %%a in ("%inputFile%") do (
    set /a "lineNum+=1"
    if !lineNum! equ 1 (
        echo %%a>>"%outputFile%"
    ) else (
        set "prevLine=!currentLine!"
        set "currentLine=%%a"
        for /f "tokens=1,* delims= " %%b in ("!prevLine!") do set "prevWord=%%b"
        for /f "tokens=1,* delims= " %%c in ("!currentLine!") do set "currentWord=%%c"
        if "!prevWord!" neq "!currentWord!" echo %%a>>"%outputFile%"
    )
)
endlocal

(for /f %%a in ('type "%inputFile%" ^| find /c /v ""') do set /a lines=%%a) >nul
set /a "lastLine=%lines% - 1"
(for /f "usebackq skip=%lastLine% delims=" %%a in ("%inputFile%") do echo %%a)
(for /f "usebackq skip=%lastLine% delims=" %%a in ("%inputFile%") do echo %%a) >>"%outputFile%"

endlocal
batch-file compare line
1个回答
0
投票

试试这个:

@echo off
setlocal enabledelayedexpansion

:: Prompt for input file name and set output file name
set /p "inputFile=Enter file name: "
set "outputFile=!inputFile!_filtered.txt"

:: Initialize variables to manage lines and statuses
set "prevStatus=none"
set "lineCount=0"
set "firstLine=none"
set "secondLine=none"

:: Read each line from the file
for /f "usebackq delims=" %%a in ("%inputFile%") do (
    set /a "lineCount+=1"
    set "currentLine=%%a"

    :: Always store the last line
    set "lastLine=%%a"

    :: Special handling for the first and second line
    if !lineCount! equ 1 (
        set "firstLine=%%a"
    ) else if !lineCount! equ 2 (
        set "secondLine=%%a"
    ) else (
        :: Split the line to get the status (OPEN or CLOSE)
        for /f "tokens=1,* delims= " %%b in ("!currentLine!") do set "currentStatus=%%b"

        :: Compare the current status with the previous one and write to output if different
        if not "!prevStatus!" equ "!currentStatus!" (
            echo !prevLine!>>"%outputFile%"
        )

        :: Update previous status and line
        set "prevStatus=!currentStatus!"
        set "prevLine=%%a"
    )
)

:: Output the first two and last line
(
    echo !firstLine!
    echo !secondLine!
    echo !lastLine!
) >> "%outputFile%"

endlocal

这是我所做的更改以及原因:

  1. 前两行输出的分离和延迟:

在原始脚本中,曾尝试专门管理前两行,但并没有完全达到目的,因为只有第一行被区别对待。为了解决这个问题,我将脚本修改为:

  • 使用专用变量(
    firstLine
    secondLine
    )分别捕获并存储第一行和第二行。这可确保这些行不会受到随后的状态比较逻辑的影响,否则可能会导致它们被错误地过滤掉。
  • 处理结束时输出这两行。通过将它们包含在输出文件中推迟到处理整个文件之后,我们可以避免在状态比较循环期间处理它们的任何问题。
  1. 状态变化逻辑的处理:

您的初始脚本尝试实现一种机制来检测状态变化,但由于执行顺序和变量处理而面临问题:

  • 改进了检测状态变化的逻辑:我现在不再直接比较行,而是分割每一行以提取状态字(“OPEN”或“CLOSE”),并将此状态与前一行的状态进行比较。这使得脚本能够准确地确定何时发生状态更改。
  • 保留上一行进行比较:通过将处理后的每一行存储为 prevLine,当后续行检测到状态变化时,脚本可以正确输出该行,确保不会遗漏任何变化。
  1. 正确包含最后一行:

原始脚本尝试包含最后一行,但由于确定文件中的总行数并相应调整处理的复杂性而未能正确处理它。为了简化并确保准确性:

  • 在每次迭代中存储最后一行:变量lastLine在每次循环时使用当前行进行更新。这样,无论脚本在哪里停止,lastLine 始终包含文件的实际最后一行。
  • 循环后直接输出最后一行:通过在处理所有其他行后直接将lastLine附加到输出文件,脚本确保始终包含文件的最后一行,无论其内容或状态如何。

最终输出处理:

处理文件后,脚本现在输出:

  • 前两行(保留最初读取的内容)。
  • 检测到与上一行相比状态发生变化的任何行。
  • 文件的最后一行。

这种方法可确保根据您的规范过滤文件内容,同时还简化了一些逻辑并使脚本更健壮且更易于维护。

© www.soinside.com 2019 - 2024. All rights reserved.