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

时间:2014-10-26 02:34:56

标签: 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

正如你所看到的,文本是随机编写的(某种程度上),这意味着某些文件有一个地址,而其中一些文件没有,所以我不能在这些行上应用任何规则,如安排\排序等等,或者我会丢失文件"姓名,地址"布置。

所以,首先我必须移动所有的地址行,一步(这是GUI中的简单部分),我能够使用 Np ++ / TextPad 正则表达式如下: - 查找:\nhttp - 替换:http,最终结果如下:

STEP.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

现在,最糟糕的部分(至少对我来说)是将匹配模式移动到他们行的开头,完全像这样:

Step.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 

现在我可以轻松地对它们进行排序,或者我需要的任何东西,没有任何风险。 所以,我的问题是: -

在命令行 CMD Cygwin : -

1-如何查找" \ n http" ,并替换为" HTTP" ?

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

如果还有其他技术,那么知道它会很棒。

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

3 个答案:

答案 0 :(得分:1)

这是一个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设置为空并跳过其余命令并跳至next行。

  • last {print last}

    如果last变量不为空,请将其打印出来。只有在没有与last行一起使用的网址时才会出现这种情况。

  • {last=$0}

    使用当前行更新last变量。在awk中,$0表示整个当前行。

  • END{if (last) print last;}

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

仅执行sed

中的第一步

只要file不是太大,这就行了:

$ 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的模式空间,然后用\nhttp代替替换http

更详细:

  • :a;N;$!b a

    这是一个循环。 :a是一个标签。 N读取模式空间中的下一行。 b a跳转到标签:a。我们希望继续循环直到文件结束。文件中的最后一行称为$,而!表示不。因此,$!b a表示跳转到标签:a,除非我们已到达文件的最后一行。

  • s/\nhttp/ http/g

    现在我们在模式空间中拥有整个文件,我们使用\nhttp替换http进行全局替换。

这是对上述内容的修改。它将线条读入模式空间,直到它到达以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前面的换行符。

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r 'N;s/(^-.*)\n(http.*)/\2\1/;P;D' file

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

答案 2 :(得分:0)

这个简短的Perl程序将按照你的要求进行。

小心备份原始文件,因为它会就地修改文件。

要编辑的文件的路径作为参数传递到命令行,如此

perl edit_file.pl mytext.txt

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