use*_*233 10 linux bash command-line pcregrep
我需要通过bash脚本检查一个文件是否在另一个文件中.对于给定的多行模式和输入文件.
返回值:
我想接收状态(在grep命令中如何)0如果找到任何匹配,如果没有找到匹配则为1.
图案:
说明
只有以下示例才能找到匹配项:
pattern file1 file2 file3 file4
222 111 111 222 222
333 222 222 333 333
333 333 444
444
Run Code Online (Sandbox Code Playgroud)
以下不应该:
pattern file1 file2 file3 file4 file5 file6 file7
222 111 111 333 *222 111 111 222
333 *222 222 222 *333 222 222
333 333* 444 111 333
444 333 333
Run Code Online (Sandbox Code Playgroud)
这是我的脚本:
#!/bin/bash
function writeToFile {
if [ -w "$1" ] ; then
echo "$2" >> "$1"
else
echo -e "$2" | sudo tee -a "$1" > /dev/null
fi
}
function writeOnceToFile {
pcregrep --color -M "$2" "$1"
#echo $?
if [ $? -eq 0 ]; then
echo This file contains text that was added previously
else
writeToFile "$1" "$2"
fi
}
file=file.txt
#1?1
#2?2
#3?3
#4?4
pattern=`cat pattern.txt`
#2?2
#3?3
writeOnceToFile "$file" "$pattern"
Run Code Online (Sandbox Code Playgroud)
我可以对所有模式行使用grep命令,但是这个例子失败了:
file.txt
#1?1
#2?2
#=== added line
#3?3
#4?4
pattern.txt
#2?2
#3?3
Run Code Online (Sandbox Code Playgroud)
或者即使你改变了行:2和3
file=file.txt
#1?1
#3?3
#2?2
#4?4
Run Code Online (Sandbox Code Playgroud)
当它不应该返回0.
我该如何解决?请注意,我更喜欢使用本机安装的程序(如果这可以没有pcregrep).也许sed或awk可以解决这个问题?
我只是diff
用于这个任务:
diff pattern <(grep -f file pattern)
Run Code Online (Sandbox Code Playgroud)
diff file1 file2
报告两个文件是否不同.
通过说grep -f file pattern
你正在看到的内容pattern
是什么file
.
所以,你在做什么是检查从什么线pattern
都在file
,然后比较这pattern
本身.如果它们匹配,则意味着它pattern
是一个子集file
!
seq 10
是的一部分seq 20
!我们来检查一下:
$ diff <(seq 10) <(grep -f <(seq 20) <(seq 10))
$
Run Code Online (Sandbox Code Playgroud)
seq 10
不完全在里面seq 2 20
(1不在第二个):
$ diff -q <(seq 10) <(grep -f <(seq 2 20) <(seq 10))
Files /dev/fd/63 and /dev/fd/62 differ
Run Code Online (Sandbox Code Playgroud)
我有一个使用 perl 的工作版本。
我以为我可以与 GNU 一起使用awk
,但事实并非如此。RS=空字符串在空行上分割。请参阅损坏的 awk 版本的编辑历史记录。
如何在文件中搜索多行模式?展示了如何使用 pcregrep,但当要搜索的模式可能包含正则表达式特殊字符时,我看不到让它工作的方法。 -F
固定字符串模式不适用于多行模式:它仍然将模式视为一组要单独匹配的行。(不是作为要匹配的多行固定字符串。)我看到您已经在尝试中使用 pcregrep 。
顺便说一句,我认为在非 sudo 情况下你的代码中有一个错误:
function writeToFile {
if [ -w "$1" ] ; then
"$2" >> "$1" # probably you mean echo "$2" >> "$1"
else
echo -e "$2" | sudo tee -a "$1" > /dev/null
fi
}
Run Code Online (Sandbox Code Playgroud)
不管怎样,使用基于行的工具的尝试都失败了,所以是时候推出一种更严肃的编程语言了,它不会强制我们使用换行符约定。只需将两个文件读入变量,并使用非正则表达式搜索:
function writeToFile {
if [ -w "$1" ] ; then
"$2" >> "$1" # probably you mean echo "$2" >> "$1"
else
echo -e "$2" | sudo tee -a "$1" > /dev/null
fi
}
Run Code Online (Sandbox Code Playgroud)
请参阅在 Perl 中将文件转换为字符串的最佳方法是什么?以避免依赖File::Slurp
(这不是标准 perl 发行版的一部分,也不是默认的 Ubuntu 15.04 系统)。我选择 File::Slurp 的部分原因是为了让非 perl 极客能够清楚地了解程序正在执行的操作,相比之下:
my $contents = do { local(@ARGV, $/) = $file; <> };
Run Code Online (Sandbox Code Playgroud)
我正在努力避免将完整文件读入内存,其想法来自http://www.perlmonks.org/?node_id=98208。我认为不匹配的情况通常仍然会立即读取整个文件。另外,处理文件前面的匹配的逻辑非常复杂,我不想花很长时间进行测试以确保它对于所有情况都是正确的。这是我放弃之前的经历:
#IO::File->input_record_separator($pat);
$/ = $pat; # pat must include a trailing newline if you want it to match one
my $fh = IO::File->new($ARGV[2], O_RDONLY)
or die 'Could not open file ', $ARGV[2], ": $!";
$tail = substr($fh->getline, -1); #fast forward to the first match
#print each occurence in the file
#print IO::File->input_record_separator while $fh->getline;
#FIXME: something clever here to handle the case where $pat matches at the beginning of the file.
do {
# fixme: need to check defined($fh->getline)
if (($tail eq '\n') or ($tail = substr($fh->getline, -1))) {
exit(0); # if there's a 2nd line
}
} while($tail);
exit(1);
$fh->close;
Run Code Online (Sandbox Code Playgroud)
另一个想法是过滤要搜索的模式和文件tr '\n' '\r'
或其他内容,因此它们都是单行的。(\r
这可能是一个安全的选择,不会与文件或模式中已有的任何内容发生冲突。)
归档时间: |
|
查看次数: |
1264 次 |
最近记录: |