在多个文件中搜索多个模式

时间:2017-03-10 02:48:14

标签: linux bash grep

这与Function to search of multiple patterns using grep

有关

我想使用以下命令搜索多个模式的多个文件:

myscript *.txt pattern1 pattern2 pattern3

我尝试在上一个问题中实现代码,但它们不适用于通配符。例如,以下操作不起作用:

#!/bin/bash

ARGS=$# 
if [ $ARGS -lt 2 ]
then 
    echo "You entered only $ARGS arguments- at least 2 are needed."
    exit 
fi

search() {
    if [ $# -gt 0 ]
    then
        local pat=$1
        shift
        grep -i "$pat" | search "$@"
    else 
         cat
    fi
}

for VAR in $1
do 
    file=$VAR
    shift
    cat "$file" | search "$@"
done

如何创建一个可以搜索多个文件的脚本(从第一个参数中取出)来搜索多个模式(从其余参数中搜索)?

1 个答案:

答案 0 :(得分:1)

您是否尝试使用findsed

find . -name *.txt -exec sed -n -e '/pattern1/p' -e '/pattern2/' '{}' ';'

-n选项将确保sed不会打印所有文件,p命令会打印匹配的行。最后,find将获得您需要的所有文件。

修改

如果您想将其放入脚本中以生成sed命令,则可以使用this trick

编辑2:

正如@shellter所说,通常最好使用选项,并且在编写脚本时,*.txt将由bash扩展。为避免这种情况,您需要引用第一个参数。

像往常一样,您的问题有几种解决方案:

解决方案1(使用内置bash):

#! /usr/bin/env bash

set -o nounset # Throw error if variable not set
set -o errexit # Exit if error is thrown

work_dir=$PWD # directory to search from

# Reading the command line
files_pattern=${1:-}; # Save first argument as files pattern.
shift 1;              # Move $1 to next argument (and propagate such as $n gets $n+1)
echo "==> Files to search follow pattern: ${files_pattern}"

_len=$#; #save the number of arguments.
for (( i=0; i<$_len; i=$i+1 )); # Go through the search patterns.
do
    search_patterns[$i]=$1; # store the next search pattern
    shift 1; # move $1 to next patern.
    echo "==> New search pattern #$i: ${search_patterns[$i]}"
done

while read -r file; # Go through all the matching files
do
    echo "==> In file: ${file}"
    while read -r line; # Go though all the lines in the file
    do
        for regex in "${search_patterns[@]}"; # iterate trough patterns
        do
            [[ "${line}" =~ $regex ]] && echo "${line}";
        done
    done < ${file}
done < <(find $work_dir -iname $files_pattern -print) # find all the files matching file_pattern

解决方案2(使用grep):

#! /usr/bin/env bash

set -o nounset # Throw error if variable not set
set -o errexit # Exit if error is thrown

work_dir=$PWD # directory to search from

# Reading the command line
files_pattern=${1:-}; # Save first argument as files pattern.
shift 1;              # Move $1 to next argument (and propagate such as $n gets $n+1)
echo "==> Files to search follow pattern: ${files_pattern}"

while [ $# -gt 0 ]; # Go through the search patterns.
do
    search_patterns+="$1"; # store the next search pattern
    shift 1; # move $1 to next patern.
    [ $# -gt 0 ] && search_patterns+="|" #Add or option
done
echo "==> Search patterns: ${search_patterns}"

cd ${work_dir} && egrep -iR '('"${search_patterns}"')' && cd -;

解决方案3(使用sed):

#! /usr/bin/env bash

set -o nounset # Throw error if variable not set
set -o errexit # Exit if error is thrown

work_dir=$PWD # directory to search from

# Reading the command line
files_pattern=${1:-}; # Save first argument as files pattern.
shift 1;              # Move $1 to next argument (and propagate such as $n gets $n+1)
echo "==> Files to search follow pattern: ${files_pattern}"

while [ $# -gt 0 ]; # Go through the search patterns.
do
    search_patterns+="/$1/p;"; # store the next search pattern
    shift 1; # move $1 to next patern.
    [ $# -gt 0 ] && search_patterns+=" " #Add or option
done
echo "==> Search patterns: ${search_patterns}"

# Will print file names, and then matching lines
find "$work_dir" -iname "$files_pattern" -print -exec sed -n "${search_patterns}" '{}' ';'

我确信还有很多其他方法可以调整或解决这个问题,但这应该可以让你开始。

祝你好运!