Batch file 如何使用CMD或Cygwin CLI工具水平移动文本模式?

Batch file 如何使用CMD或Cygwin CLI工具水平移动文本模式?,batch-file,awk,sed,cmd,cygwin,Batch File,Awk,Sed,Cmd,Cygwin,我不知道这在命令行中是否可行,但无论如何,我想做的是: 我有一个这样写的文本文件 - FileName1.txt http://example.com/AnyName-For-File-1.txt - FileName2.txt - FileName3.txt - FileName4.txt http://example.com/AnyName-For-File-4.txt - FileName5.txt http://example.com/AnyName-For-File-5.txt 正如

我不知道这在命令行中是否可行,但无论如何,我想做的是:

我有一个这样写的文本文件

- FileName1.txt
http://example.com/AnyName-For-File-1.txt
- FileName2.txt
- FileName3.txt
- FileName4.txt
http://example.com/AnyName-For-File-4.txt
- FileName5.txt
http://example.com/AnyName-For-File-5.txt
正如你所看到的,文本是随机写的(不知何故),这意味着有些文件有地址,有些没有,所以我不能在这些行上应用任何规则,比如排列\排序等等,否则我将丢失文件的“名称、地址”排列

因此,首先我必须移动所有的地址行,一步一步(这是GUI中最简单的部分),然后我可以使用Np++/TextPadRegex如下:-查找:
\nhttp
-替换:
http
,最终结果如下:

步骤1:-

- FileName1.txt http://example.com/AnyName-For-File-1.txt
- FileName2.txt
- FileName3.txt
- FileName4.txt http://example.com/AnyName-For-File-4.txt
- FileName5.txt http://example.com/AnyName-For-File-5.txt
现在,最糟糕的部分(至少对我来说)是将匹配模式移动到行的开头,就像这样:

步骤2:-

http://example.com/AnyName-For-File-1.txt- FileName1.txt
- FileName2.txt
- FileName3.txt
http://example.com/AnyName-For-File-4.txt- FileName4.txt 
http://example.com/AnyName-For-File-5.txt- FileName5.txt 
现在我可以很容易地对它们进行分类,或者我需要的任何东西,而不会有任何风险。 所以,我的问题是:-

在命令行CMDCygwin中:-

1-如何查找“\nhttp”,并替换为“http”

2-如何将匹配模式(文件地址,从http移动到.txt)移动到行首

此外,如果有任何其他技术,它将是伟大的知道它


在这样一个伟大的社区里,非常感谢你们提供的帮助。非常感谢您的帮助:)

这里有一个
awk
命令,我想它可以满足您的需要:

$ awk '/^http/{print $0 last;last="";next} last {print last} {last=$0} END{if (last) print last;}' file2
http://example.com/AnyName-For-File-1.txt- FileName1.txt
- FileName2.txt
- FileName3.txt
http://example.com/AnyName-For-File-4.txt- FileName4.txt
http://example.com/AnyName-For-File-5.txt- FileName5.txt
工作原理 脚本有一个变量,
last
,它包含前一行的内容
awk
隐式循环输入文件中的每一行

  • /^http/{print$0 last;last=”“;next}

    如果当前行以http开头,则将其与前一行一起打印。将
    last
    设置为空,跳过其余命令并跳到
    下一行

  • last{print last}

    如果
    last
    变量不是空的,请打印它。只有在最后一行
    没有URL时才会发生这种情况

  • {last=$0}

    用当前行更新
    last
    变量。在
    awk
    中,
    $0
    表示当前行的全部

  • END{if(last)print last;}

    在输入结束时,如果
    last
    中仍有一行,则将其打印出来。只有当最后一行是缺少URL的文件名时,才会发生这种情况

仅执行sed中的第一步 只要
文件
不是太大,这将起作用:

$ sed  ':a;N;$!b a;s/\nhttp/ http/g' file
- FileName1.txt http://example.com/AnyName-For-File-1.txt
- FileName2.txt
- FileName3.txt
- FileName4.txt http://example.com/AnyName-For-File-4.txt
- FileName5.txt http://example.com/AnyName-For-File-5.txt
其工作原理是将整个文件读入sed的模式空间,然后用
http
替换
\nhttp

更详细地说:

  • :a;N、 美元!b a

    这是一个循环<代码>:a
    是一个标签
    N
    将下一行读入模式空间<代码>b a
    跳转到标签
    :a
    。我们希望继续此循环直到文件结束。文件中的最后一行称为
    $
    表示没有。所以,
    $!b a
    表示跳转到标签
    :a
    ,除非我们已经到达文件的最后一行

  • s/\nhttp/http/g

    既然模式空间中有了整个文件,我们就用
    http
    替换
    \nhttp

这是上面的一个变体。它将行读入模式空间,直到到达以
http
开头的行为止。然后,它从该行前面删除换行符:

$ sed ':a;N;/http/!b a; s/\nhttp/ http/' file
- FileName1.txt http://example.com/AnyName-For-File-1.txt
- FileName2.txt
- FileName3.txt
- FileName4.txt http://example.com/AnyName-For-File-4.txt
- FileName5.txt http://example.com/AnyName-For-File-5.txt
由于这种方法不会一次读入整个文件,因此如果文件较大,则更容易占用内存

更详细地说:

  • :a;N/http/!b a

    如上所述,这是一个循环。它不断分支回到标签
    :a
    读取另一行,直到我们得到一行包含
    http

  • s/\nhttp/http/

    这将用空格替换
    http
    前面的换行符


    • 这个简短的Perl程序将按照您的要求执行

      备份原始文件时要小心,因为它会修改文件

      要编辑的文件的路径在命令行上作为参数传递,如下所示

      perl edit_file.pl mytext.txt
      

      这可能适用于您(GNU-sed):


      一次读取两行,如果模式匹配,则将第2行替换为第1行(删除换行符)。那些不匹配的行按原样打印。

      非常感谢兄弟,我真的很感动!!你怎么能想到那样的事?!我甚至不需要修改你命令中的模式!但是,请允许我问您(只是为了了解情况)如何在CLI中执行第一步?我的意思是,在NP++中,我使用了这个,Find:\nhttp-Replace:http将http行向上移动一步,那么如何使用sed或perl来做同样的事情呢。。。非常感谢你的帮助。。。karim@ENG.KARIM谢谢我在答案中添加了一个示例,说明如何在
      sed
      中执行第一步。返回!我回来只是想说声谢谢约翰,非常感谢你的帮助。你无法想象你为我节省了多少时间……再次感谢你,potong的代码也很棒,但是你关于文件大小的提示,让我不知何故担心使用Sed,因为我几乎每个文件都有10.000行!我希望我能投票支持你的答案,但正如你所看到的,我还不能这么做。。。非常感谢你,兄弟,你的命令很完美。玩得开心:)
      use strict;
      use warnings;
      
      use Tie::File;
      
      tie my @file, 'Tie::File', shift or die $!;
      
      for ( my $i = 1; $i < @file; ) {
      
        if ( $file[$i] =~ m<^http://>i ) {
          $file[$i] .= $file[$i-1];
          splice @file, $i-1, 1;
          next;
        }
      
        ++$i;
      }
      
      http://example.com/AnyName-For-File-1.txt- FileName1.txt
      - FileName2.txt
      - FileName3.txt
      http://example.com/AnyName-For-File-4.txt- FileName4.txt
      http://example.com/AnyName-For-File-5.txt- FileName5.txt
      
      sed -r 'N;s/(^-.*)\n(http.*)/\2\1/;P;D' file