bash 使用bash在文件中查找字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17157466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:43:03  来源:igfitidea点击:

find string in file using bash

linuxbash

提问by Mickey Tin

I need to find strings matching some regexp patternand represent the search result as array for iterating through it with loop ), do I need to use sed? In general I want to replace some strings but analyse them before replacing.

我需要找到匹配的字符串regexp pattern并将搜索结果表示为数组以使用循环遍历它),我需要使用sed吗?一般来说,我想替换一些字符串,但在替换之前先分析它们。

回答by perreal

Using sedand diff:

使用seddiff

sed -i.bak 's/this/that/' input
diff input input.bak

GNU sedwill create a backup file before substitutions, and diffwill show you those changes. However, if you are not using GNU sed:

GNUsed将在替换之前创建一个备份文件,diff并将向您显示这些更改。但是,如果您不使用 GNU sed

mv input input.bak
sed 's/this/that/' input.bak > input
diff input input.bak

Another method using grep:

另一种方法使用grep

pattern="/X"
subst=that
while IFS='' read -r line; do
    if [[ $line = *"$pattern"* ]]; then
        echo "changing line: $line" 1>&2
        echo "${line//$pattern/$subst}"
    else
        echo "$line"
    fi  
done < input > output

回答by Riot

The best way to do this would be to use grepto get the lines, and populate an array with the result using newline as the internal field separator:

执行此操作的最佳方法是使用grep获取行,并使用换行符作为内部字段分隔符使用结果填充数组:

#!/bin/bash

# get just the desired lines
results=$(grep "mypattern" mysourcefile.txt)

# change the internal field separator to be a newline
IFS=$'/n'

# populate an array from the result lines
lines=($results)

# return the third result
echo "${lines[2]}"

You could build a loop to iterate through the results of the array, but a more traditional and simple solution would just be to use bash's iteration:

您可以构建一个循环来迭代数组的结果,但更传统和更简单的解决方案是使用 bash 的迭代:

for line in $lines; do
  echo "$line"
done

回答by Mike Q

FYI: Here is a similar concept I created for fun. I thought it would be good to show how to loop a file and such with this. This is a script where I look at a Linux sudoers file check that it contains one of the valid words in my valid_words array list. Of course it ignores the comment "#" and blank "" lines with sed. In this example, we would probably want to just print the Invalid lines only but this script prints both.

仅供参考:这是我为了好玩而创建的类似概念。我认为展示如何循环文件等会很好。这是一个脚本,我在其中查看 Linux sudoers 文件,检查它是否包含我的 valid_words 数组列表中的有效单词之一。当然,它会忽略带有 sed 的注释“#”和空白“”行。在这个例子中,我们可能只想打印 Invalid 行,但这个脚本打印了两者。

#!/bin/bash

# -- Inspect a sudoer file, look for valid and invalid lines.

file=""
declare -a valid_words=( _Alias = Defaults includedir )

actual_lines=$(cat "${file}" | wc -l)
functional_lines=$(cat "${file}" | sed '/^\s*#/d;/^\s*$/d' | wc -l)

while read line ;do

    # -- set the line to nothing "" if it has a comment or is empty line.
    line="$(echo "${line}" | sed '/^\s*#/d;/^\s*$/d')"

    # -- if not set to nothing "", check if the line is valid from our list of valid words.
    if ! [[ -z "$line" ]] ;then

        unset found 
        for each in "${valid_words[@]}" ;do
            found="$(echo "$line" | egrep -i "$each")"
            [[ -z "$found" ]] || break;
        done

        [[ -z "$found" ]] && { echo "Invalid=$line"; sleep 3; } || echo "Valid=$found"

    fi

done < "${file}"

echo "actual lines: $actual_lines  funtional lines: $functional_lines"