Mickey Tin
Mickey Tin

Reputation: 3543

find string in file using bash

I need to find strings matching some regexp pattern and 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.

Upvotes: 3

Views: 11744

Answers (3)

Mike Q
Mike Q

Reputation: 7337

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.

#!/bin/bash

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

file="${1}"
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"

Upvotes: 0

Riot
Riot

Reputation: 16746

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

#!/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:

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

Upvotes: 3

perreal
perreal

Reputation: 98118

Using sed and diff:

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

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

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

Another method using 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

Upvotes: 6

Related Questions