【问题标题】:How to Ignore cases,space and blank lines when comparing text between two files比较两个文件之间的文本时如何忽略大小写、空格和空行
【发布时间】:2019-05-15 12:33:14
【问题描述】:

所以我写了一个脚本来比较两个文件

所以我的文件是 文件1:

This is line 1.
This is line 2.
This is line 3.
This is line 4.
This is line 5.

文件 2:

this is line 1,aaa
this is line 2,bbb
this is line 3,ccc

所以我的代码所做的是查找逗号前面的句子(在 file2 中)是否存在于文件中,如果存在,则将其替换为逗号后面的句子。

这是我的代码

awk -F'"(,")?' '
NR==FNR { r[$2] = $3; next }
{ for (n in r) gsub(n, r[n]) } 1' file2.csv file1.csv>output.csv

所以我的 output.csv 应该如下所示:

aaa
bbb
ccc
This is line 4.
This is line 5.

只要文件和空格中的大小写不匹配,此代码就可以正常工作。 所以在比较时,我希望它以不区分大小写的方式进行比较并修剪空格。 例如:

When comparing:
file1:
thisisline1.
thisisline2.
thisisline3. etc

并且输出应该是原始格式

This is line 1.

我正在寻找的是即时修剪和小写转换

编辑:使这个问题关于修剪部分更清楚。 我已经写好了代码:

cat file2.csv|tr -s ' '>file3.csv

它的作用是将多个空格合并为一个 所以

This is line 1.

相同
This   is line 1.

但是如果存在带有一个或多个空格的空行,就会出现问题 例如:

this is line 1,aaa
this is line 2,bbb
(blank line but with space)
this is line 3,ccc
this is line 4.
this is line 5. 

所以当我先使用我的 awk 命令然后使用修剪功能时,它会失败。 所以即使有了这个文件,我的输出也应该是

aaa
bbb
ccc
This is line 4.
This is line 5.

【问题讨论】:

  • 能否在您的帖子中提及更清晰的预期输出。
  • 您的样本输入不足以测试解决方案是否有效。您应该包括 RE 元字符和反向引用字符以及作为其他行子集的行,部分匹配的行,包含逗号的行,以及仅在空格中不同的行,但一些有助于分离工作的测试用例来自非工作的“解决方案”。

标签: awk tr


【解决方案1】:
$ cat tst.awk
{
    key = tolower($0)
    gsub(/[[:space:]]+/," ",key)
}
NR==FNR {
    val = $0
    sub(/,[^,]+$/,"",key)
    sub(/.*,/,"",val)
    key2val[key"."] = val
    next
}
{ print (key in key2val ? key2val[key] : $0) }

$ awk -f tst.awk file2 file1
aaa
bbb
ccc
This is line 4.
This is line 5.

【讨论】:

  • 我正在寻找修改我的代码来完成这项任务。这显然可以为提供的示例文件完成工作。但是如果我要在我的 file1 中添加逗号,例如这是第 1 行,它会失败工作。我的代码也适用于此,但我只想在比较时忽略大小写和空格。感谢这个解决方案
  • a) 您的代码是完全错误的方法,并且会因为我之前提到的各种输入字符串而失败,所以不要尝试增强它,重新开始。 b) 我的代码可以在 file1 中使用逗号 - 如果您有反例,请编辑您的问题以将其包含在您的示例输入/输出中。
  • 问题是有一个标准格式,我将在其中创建我的 file1 和 file2。所以我的代码适用于该格式。我试图忽略空格和大小写的原因是为了说明创建这些文件时可能发生的任何人为错误(间距不一致或大小写错误)。
  • 这很好,但是在给定一些输入字符串的情况下,您的代码仍然会失败,并且简单地不使用该方法并改用健壮的方法是微不足道的。如果您愿意,可以使用它,它是您的应用程序。
【解决方案2】:

如果你正在考虑 Perl,你可以使用下面的

> cat anuj_f2 
this is line 1,aaa
this is line 2,bbb
this is line 3,ccc
> cat anuj_f1
This is line 1.
This is line 2.
This is line 3.
This is line 4.
This is line 5.
> perl -F"," -lane ' $kv{lc $F[0]."."}=$F[1] if $ARGV eq "anuj_f2"; if( $ARGV eq "anuj_f1" ) {s/$_/$kv{lc $_}?$kv{lc $_}:$_/ige;print } ' anuj_f2 anuj_f1
aaa
bbb
ccc
This is line 4.
This is line 5.
> 

【讨论】:

  • 感谢伙伴的努力。但是我目前不关注 PERL 并坚持使用 awk。
【解决方案3】:

请用tolow检查一下

awk -F'"(,")?' '
NR==FNR { r[$2] = $3; next }
{ for (n in r) gsub(tolower(n), tolower(r[n])) } 1' file2.csv file1.csv>output.csv

你也可以使用

IGNORECASE=1

Reference

【讨论】:

  • IGNORECASE=1 似乎适用于我的情况。谢谢,我会在较大的文件上尝试这两种解决方案并告诉你。
  • 谢谢。如果您觉得我们的回答对您有帮助,请考虑投票和/或接受它作为解决方案。问候
  • 如果/当输入包含 RE 元字符和/或反向引用字符时将失败,并且由于部分匹配而失败。这是问题中样本输入/输出不足的众多情况之一,这使得它看起来像它实际上通常不起作用。不要这样做。
  • IGNORECASE=1 添加到我的代码时也适用于较大的文件。 tolower() 解决方案的问题在于它永久更改了 file2 的内容,这是不受欢迎的。谢谢
  • 谢谢。如果您觉得我们的回答对您有帮助,请考虑投票和/或接受它作为解决方案。问候
猜你喜欢
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 2016-05-05
  • 2021-03-25
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多