1

昨日作業していたのと同じスクリプトの別の問題について投稿して申し訳ありません。

元々cd、スペースを含むパスに問題がありましたが、現在は修正されています。問題は、スクリプトに 3 番目の引数が与えられた場合、以前に見つかったファイル内でそれを検索し、ファイルの場所と用語が見つかった行番号を出力することです。

何らかの理由grepで、スペースを含むファイルへのパスが好きではありません (これも正しいですか? -.-) 変数を二重引用符で囲んでいますgrep

誰かがそれを修正する方法について何か考えを持っていますか?

#!/bin/bash

path = $1 #1st arg is the path to be searched
regex = $2 #2nd arg is a regular expression
searchTerm = $3 #3rd arg is an optional search term
startDir = `pwd` #Stores the starting path
getDirs()
{ #Function to get the directories
    for i in "$1"
    ; do
        if [ -d "$i" ]; then
            echo "$i" >> temp.txt
            getDirs "$i"
        fi
    done
}

getFiles() {        # Function to get files matching the regex

    while IFS= read -r path; do # While there is a line, read it, backslash is not a delimiter
        cd "$path"

        temp=`ls -1 | grep "$regex"`    #List the contents of the dir. Store only files that match the regex

        for j in $temp
        do
            echo "$path/$j" # For every file stored, print its location
        done
        cd $startDir
    done < temp.txt # Read from temp.txt
}

searchFiles() { # Function to search within files


    for a in $output1 # For every file found
    do
        out=`grep -n "$searchTerm" "$a" | cut -d: -f 1` # Find the line numbers in which it is present, stop showing after 1st :
        for i in $out   # For every line found
        do
            echo "$a: line $i"  # Print the file location, and the line numbers of the terms
        done
    done
}

numArgs=$#

echo "$path" >> temp.txt
getDirs $path   # Getting directories to search

output1=`getFiles`

cd $startDir

if [ $numArgs == 3 ] # If a search term is specified
then
    searchFiles # Then search the files for it
else
    echo "$output1" # Otherwise, just print the location of the files
fi

rm temp.txt # Removing temporary files
exit 0
4

1 に答える 1

1

スクリプトには、引用符で囲まれていない変数や誤って引用されている変数など、多くの問題があります。getFiles 関数を最小限に記述する必要がある方法は次のとおりです (grep が本当に必要かどうかや echo の使用などの問題は他にもありますが、それらには触れていないので、これは深刻な問題を強調しています):

getFiles() {        # Function to get files matching the regex

    while IFS= read -r path; do # While there is a line, read it, backslash is not a delimiter

        if cd "$path"; then

            oIFS="$IFS" # save then reset and restore IFS to avoid work splitting on spaces, except newlines.
            IFS=$'\n' tempA=( $(ls -1 | grep "$regex") )    #List the contents of the dir. Store only files that match the regex
            IFS="$oIFS"

            for j in "${tempA[@]}"
            do
                echo "$path/$j" # For every file stored, print its location
            done
            cd "$startDir"

        fi

    done < temp.txt # Read from temp.txt
}

「temp」は文字列ではなく配列になっていることに注意してください。そのため、一度に 1 つずつ含まれるファイル名にアクセスし、それぞれを引用符で囲むことができます。配列であることを明確にするために、名前を tempA に変更しました。

したがって、スクリプトを更新して、上記のように文字列の代わりに配列を使用してファイル名を保持し、割り当ての前後のスペースを取り除き、すべての変数を引用し、バッククォートの代わりに $(...) を使用し、thenに変更grep -n "$searchTerm" "$a" | cut -d: -f 1します。awk -v st="$searchTerm" '$0~st{print NR}' "$a"それでも問題がある場合は再投稿してください。

于 2013-01-06T15:30:52.143 に答える