如何在文本文件中交换奇数和偶数行?

时间:2017-02-19 10:21:40

标签: windows file batch-file cmd

我有一个文本文件。我必须交换奇数和偶数行。

我制作了一个批处理脚本,将偶数行写入testfile2.txt,将奇数行写入testfile3.txt

@echo off 
setlocal EnableDelayedExpansion
set "filepath1=C:\\Users\\andyb\\Desktop\\testfile.txt"
set "filepath2=C:\\Users\\andyb\\Desktop\\testfile2.txt"
set "filepath3=C:\\Users\\andyb\\Desktop\\testfile3.txt"
set counter=0
set B=0
for /F %%A in (%filepath1%) do (
set /a B=!counter!%%2
if !B! equ 0 (echo %%A>>%filepath2%) else (echo %%A>>%filepath3%)
set /A counter=counter+1
)  

我想从包含奇数行的文件中取1行,然后从偶数行的文件中取1行并将其写入我的第一个文件。但我不知道如何在 FOR 循环中执行此操作,因为它只从一个文件中读取一行,而且我无法在此循环中使用另一个文件。

输入文件示例:

1a
2b
3c
4d

输出文件示例:

2b
1a
4d
3c

4 个答案:

答案 0 :(得分:2)

尝试以下方法:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

rem // Define constants here:
set "_FILE=textfile.txt"

rem // Count number of lines:
for /F %%C in ('^< "!_FILE!" find /C /V ""') do set "COUNT=%%C"
rem // Divide by two, round up:
set /A "COUNT=(COUNT+1)/2"

< "!_FILE!" > "!_FILE!.tmp" (
    rem // Read files in blocks of two lines:
    for /L %%I in (1,1,%COUNT%) do (
        set "LINE1=" & set "LINE2="
        set /P LINE1=""
        set /P LINE2=""
        echo(!LINE2!
        echo(!LINE1!
    )
)

rem // Overwrite original file:
> nul move /Y "!_FILE!.tmp" "!_FILE!"

endlocal
exit /B

答案 1 :(得分:0)

以下示例将创建来自testfile.txt的两个文件,file0.out包含偶数行,file1.out包含奇数行。

@Echo Off
SetLocal EnableDelayedExpansion
For /F "Tokens=1* Delims=:" %%A In ('FindStr/N "^" "testfile.txt"') Do (
    Set/A "_=%%A%%2"
    (Echo(%%B)>>file!_!.out)

根据您的要求重命名输出文件

答案 2 :(得分:0)

这项任务有几种解决方案。

第一个使用延迟扩展来执行交换奇数行和偶数行的所有批处理文件行。这意味着它不适用于带有感叹号的行,因为!已从行中删除。

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "SourceFile=%USERPROFILE%\Desktop\TestFile.txt"
if not exist "%SourceFile%" goto EndBatch
set "TargetFile=%USERPROFILE%\Desktop\TestFile2.txt"
del "%TargetFile%" 2>nul

set "LineOdd="
for /F "usebackq delims=" %%I in ("%SourceFile%") do (
    if not defined LineOdd (
        set "LineOdd=%%I"
    ) else (
        echo %%I>>"%TargetFile%"
        echo !LineOdd!>>"%TargetFile%"
        set "LineOdd="
    )
)

if defined LineOdd echo !LineOdd!>>"%TargetFile%"
move /Y "%TargetFile%" "%SourceFile%"

:EndBatch
endlocal

FOR 会跳过空白行和空行,因此目标文件中缺少这些行。以分号;开头的行在 FOR 读取每一行时会被忽略,因此输出文件中也会丢失。但是根据输入示例,这些限制在这里并不重要。

使用此批处理代码可以避免第一种解决方案的局限性,当然要慢得多:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFile=%USERPROFILE%\Desktop\TestFile.txt"
if not exist "%SourceFile%" goto EndBatch
set "TargetFile=%USERPROFILE%\Desktop\TestFile2.txt"
del "%TargetFile%" 2>nul

set "LineOdd="
for /F "tokens=1* delims=:" %%H in ('%SystemRoot%\System32\findstr.exe /N /R "^" "%SourceFile%"') do (
    if not defined LineOdd (
        set "LineOdd=_%%I"
    ) else (
        if "%%I" == "" (
            echo/>>"%TargetFile%"
        ) else (
            echo %%I>>"%TargetFile%"
        )
        setlocal EnableDelayedExpansion
        if "!LineOdd!" == "_" (
            echo/>>"%TargetFile%"
        ) else (
            echo !LineOdd:~1!>>"%TargetFile%"
        )
        endlocal
        set "LineOdd="
    )
)

if defined LineOdd (
    setlocal EnableDelayedExpansion
    if "!LineOdd!" == "_" (
        echo/>>"%TargetFile%"
    ) else (
        echo !LineOdd:~1!>>"%TargetFile%"
    )
    endlocal
)
move /Y "%TargetFile%" "%SourceFile%"

:EndBatch
endlocal

也可以使用Dave Benham编写的混合批处理文件JREPL.BAT

call jrepl.bat "^(.*)\r\n(.*)\r\n" "$2\r\n$1\r\n" /M /X /F "%USERPROFILE%\Desktop\TestFile.txt" /O "%USERPROFILE%\Desktop\TestFile2.txt"
move /Y "%USERPROFILE%\Desktop\TestFile2.txt" "%USERPROFILE%\Desktop\TestFile.txt"

如果使用此解决方案是偶数行,则文件的最后一行必须具有DOS / Windows行终止(回车符\ r和换行符\ n)。

要了解使用的命令/可执行文件/批处理文件及其工作方式,请打开命令提示符窗口,在此处执行以下命令行,并完全阅读为每个命令/可执行文件/批处理文件显示的所有帮助页面。< / p>

  • del /?
  • echo /?
  • endlocal /?
  • findstr.exe /?
  • for /?
  • goto /?
  • if /?
  • jrepl.bat /?
  • move /?
  • set /?
  • setlocal /?

另请阅读Microsoft有关Using Command Redirection Operators的文章,了解2>nul>>的解释。

答案 3 :(得分:0)

我认为以相反的顺序重新交错奇数和偶数版本并不困难。附加到Compo的尝试:

2b
1a
4d
3c

5e

如果总数不均匀,则第二个最后一行将为空。示例输出:

<!DOCTYPE html>
<html>

<head>
    <title>Login</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="img/png" href="img/favicon.png" />
    <link rel="stylesheet" type="text/css" href="../css/style.css">
    <!-- <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Tangerine"> -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
    <link rel="stylesheet" href="../bower_components/angular-material/angular-material.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <!-- <script src="../js/jquery-3.1.1.min.js"></script>-->
    <link rel="stylesheet" type="text/css" href="../bower_components/angular-material-data-table/dist/md-data-table.min.css" />
</head>

<body layout="row">
    <div layout="column" flex id="content" role="main" ng-controller="AppCtrl" ng-app="MyApp">
        <md-content layout="vertical" flex id="content" layout-align="center center">
            <?php include "connect.php"; if(isset($_POST['username']) && isset($_POST['password'])){ $username=$ _POST['username']; $password=md5($_POST[ 'password']); $stmt=$ db->prepare("SELECT * FROM login WHERE username=? AND password=? "); $stmt->bindParam(1, $username); $stmt->bindParam(2, $password); $stmt->execute(); $row = $stmt->fetch(); $user = $row['username']; $pass = $row['password']; $id = $row['id']; $type = $row['type']; if($user==$username && $pass==$password){ session_start(); $_SESSION['username'] = $user; $_SESSION['password'] = $pass; $_SESSION['id'] = $id; $_SESSION['type'] = $type; ?>
            <script>
                window.location.href = 'index.php'
            </script>
            <?php } else { ?>
            <div>
                <strong>Warning!</strong> Password or username are wrong!
            </div>
            <?php } } ?>
            <form method="post" name="loginForm" style="width:50vh">
                <br />
                <br />

                <md-toolbar>
                    <div class="md-toolbar-tools">
                        <h2>Login</h2>
                    </div>
                </md-toolbar>

                <md-dialog-content>
                    <div>
                        <md-input-container class="md-block">
                            <label>Username:</label>
                            <input name="username" required>
                        </md-input-container>
                        <md-input-container class="md-block">
                            <label>Password:</label>
                            <input type="password" name="password" required>
                        </md-input-container>
                    </div>
                </md-dialog-content>

                <md-dialog-actions layout="row">
                    <span flex></span>
                    <md-button type="submit" value="Login" class="md-primary">OK</md-button>
                    <md-button type="button" aria-label="Cancel">Cancel</md-button>
                </md-dialog-actions>
            </form>
        </md-content>

    </div>

    <script src="../bower_components/angular/angular.js"></script>
    <script src="../bower_components/angular-aria/angular-aria.js"></script>
    <script src="../bower_components/angular-animate/angular-animate.js"></script>
    <script src="../bower_components/angular-material/angular-material.js"></script>
    <script src="../bower_components/angular-material-data-table/dist/md-data-table.min.js"></script>
    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> -->
    <!-- <script src="js/app.js"></script> -->
    <script>
        angular.module('MyApp', ['ngMaterial'])

        .controller('AppCtrl', function($scope) {

            $scope.radek = "Radek";
            console.log($scope.radek);

        });
</script>
</body>
</html>