删除大文件(10GB)中的新行n



我有一个大文件1.txt包含:

User: Test1
Password: P@sawFia1_f
User: Test2
Password: C99vijJiDB9fo@K!!1

我使用sed -i '/nPassword/ s///g' 1.txt删除新行与密码:但它没有删除它。为什么?最终输出需要是:

User: Test1;P@sawFia1_f
User: Test2;C99vijJiDB9fo@K!!1

假设行是这样配对的,您可以使用以下命令:

perl -pe'
s/^User:.*Kn/;/;
s/^Password:s*//;
' file.in >file.out

(可以按原样使用,也可以放在一行)

使用任何awk,给定您提供的示例输入/输出,您所需要的是:

$ awk -v RS= '{print $1, $2 ";" $4}' file1.txt
User: Test1;P@sawFia1_f
User: Test2;C99vijJiDB9fo@K!!1

或者如果您确实需要在每个输出行之间空行:

$ awk -v RS= -v ORS='nn' '{print $1, $2 ";" $4}' file1.txt
User: Test1;P@sawFia1_f
User: Test2;C99vijJiDB9fo@K!!1

如果这不是你需要的全部,那么请编辑你的问题,包括更多真正具有代表性的样本输入/输出,包括上述不适用的情况。

假设:

  • 每个User:行后面跟着一个Password:
  • 实际密码值不包含空白
  • 每个User/password组合后面跟着一个空行
  • 文件中的所有其他行都被忽略/丢弃(否则OP应该更新示例输入以显示如何处理其他数据行)

一个awk方法:

$ awk '/^User:/ {printf "%s",$0} /^Password:/ {printf ";%snn",$2}' 1.txt
User: Test1;P@sawFia1_f
User: Test2;C99vijJiDB9fo@K!!1

一旦OP确认脚本按需要工作,并且假设OP想要覆盖原始文件,并且假设OP正在运行GNU awk, OP可以添加-i inplace标志以覆盖1.txt,例如:

awk -i inplace '/^User:/ { printf "%s", $0 } /^Password:/ { printf ";%snn",$2}' 1.txt

假设UserPassword行后面跟着一个空行

perl -i.bak -00 -wpe's/nPassword:s*/;/' file

按段落读取文件(通过-00开关),因此对字符串中的每对行应用正则表达式。

-i.bak更改输入文件"in place"但也保留了一个备份(file.bak)。如果你不想要备份,只要删除.bak部分,一旦它都经过良好的测试。


或者,逐行处理

perl -i.bak -wnlE'/^Password:s*(.*)/ ? say "$u;$1" : /^User/ ? $u=$_ : say' file

这也适用于并重印任何其他行。

如果中间只有空行,且不需要保留,则简化为

perl -i.bak -wnlE'/^Password:s*(.*)/ ? say "$u;$1" : ($u=$_)' file

对于您所展示的示例,请尝试遵循awk代码,在GNUawk中编写和测试。

awk -v RS='(^|n)User:[^n]*nPassword:[^n]*' '
RT{
sub(/^n/,"",RT)
sub(/n/,";",RT)
print RT
}
' Input_file

解释:使用GNUawk,将RS(记录分隔符)设置为(^|n)User:[^n]*nPassword:[^n]*(在后面进一步解释)。在awk的主要部分检查RT是否为非NULL,然后用NULL替换开始的新行,然后用;替换新行,最后根据需要的输出打印其值。

注意:上面将在终端上打印输出,一旦您对结果满意,您可以使用GNUawk-i inplace选项,将上面代码中的awk更改为awk -i inplace

以上代码的一行形式:

awk -v RS='(^|n)User:[^n]*nPassword:[^n]*' 'RT{sub(/^n/,"",RT);sub(/n/,";",RT);print RT}' Input_file

我使用sed -i '/nPassword/ s///g' 1.txt来删除新行密码:但它没有删除它。为什么?

你误解了GNUsed的工作原理。在基本用法中,它确实对每行应用更改,后者理解为文件开始或换行和文件结束或换行之间的字符,因此这样的行不包含换行。您的任务需要在获取一行输出之前知道2行输入。这可以利用GNUsed被称为保持空间的特性来实现,让file.txt的内容为

User: Test1
Password: P@sawFia1_f
User: Test2
Password: C99vijJiDB9fo@K!!1

然后

sed -e '/^User/{h;d}' -e '/^Password/{H;g;s/nPassword: /;/}' file.txt

给输出

User: Test1;P@sawFia1_f
User: Test2;C99vijJiDB9fo@K!!1

解释:

  • 对于以User开头的行,保存当前行为hold (h),然后转到下一行(d)
  • 对于以Password开头的行,将换行符和当前行附加到hold (H),然后将当前行内容设置为hold (g)的内容,然后将换行符后面加Password后面加:后面加空格(使用分号)。

免责声明:这个解决方案假设每一行以User开头的行后面总是跟一个以Password开头的行,每一行以Password开头的行前面都是一个以User开头的行。

(在GNU sed 4.2.2中测试)

最新更新