Bash

grep 和 IFS 的非常奇怪的行為

  • April 30, 2013

我在使用 grep 時遇到問題,返回的結果是“n-empty”,我的意思是沒有 ’n’ 字元…

這是腳本範例:

OLDIFS=$IFS
IFS="\\n"

i=$(grep -ril $1 *)

echo $i

IFS=$OLDIFS

我試過了IFS='\n'IFS="\n"只有當我擺脫 IFS 時,結果才會顯示正確的路徑……

我在for theFile in $i; do......done循環中使用結果,結果以正確的方式使用並theFile正確顯示

唯一的問題是我沒有正確的控制台/文件輸出$i,這是一個戰略數據:

我在控制台中看到的內容和寫入的文件(範例):

LecteurSy dicatio _sy dic/fiche_93.xml

應該顯示和書寫的內容(範例):

LecteurSyndication_syndic/fiche_93.xml

任何的想法 ?

編輯:在家玩的完整腳本;)

#!/bin/bash

monTerminal=$(tty) ; monTerminal=${monTerminal:9}
fichier="/home/importts/tmpCmdOpenFirst$monTerminal.xml"

PWD="`pwd`"
echo "== Recherche dans les fiches  ==" > "$fichier"

echo "Recherche : $1" >> "$fichier"
echo "Dans      : $PWD" >> "$fichier"

OLDIFS=$IFS
IFS="\\n"

i=$(grep -ril $1 *)

echo $i

echo "== Liste des fichiers trouves ==" >> "$fichier"

echo $i >> "$fichier"

IFS=$OLDIFS


#while read uneFiche
for uneFiche in $i;
do

echo "================================" >> "$fichier"
echo "== $uneFiche" >> "$fichier"
echo "================================" >> "$fichier"
echo "" >> "$fichier"

xmlindent "$uneFiche" >> "$fichier"

done < /home/robert/tmpCmdOpenFirst_liste.txt

nano "$fichier"
#rm $fichier

首先,您已設置IFS\n,而不是換行符。在 bash 中,您可以使用$'…'將反斜杠序列解釋為控製字元:

IFS=$'\n'

或者您可以選擇使用文字換行符。

IFS='
'

第二個問題是IFS擴展變數時很重要。所以在展開的時候需要設置$i,其實什麼時候設置都無所謂i

i=$(grep -ril -e "$1" -- *)
set -f; OLDIFS="$IFS"; IFS='
'
for uneFiche in $i; do
 set +f; IFS="$OLDIFS"
 …
done
set +f; IFS="$OLDIFS"

此外,不要忘記在不拆分時引用變數,例如傳遞給grep. 如果模式以 開頭,請使用選項-將其傳遞給。如果第一個文件名以 . 開頭,還要放在文件名的前面。此外,如果文件名包含 glob 字元,請在不引用變數擴展之前關閉 glob 。grep``-e``--``-``set -f

一種更簡單的方法是呼叫grep循環內的每個文件。另外一個好處是,您的腳本不會中斷包含換行符的文件名。

for uneFiche in *; do
 if grep -qri -e "$1" -- "$uneFiche"; then
   …
 fi
done

遵循您的問題描述並不容易。缺少唯一有用的資訊,即grep -ril $1 *(或者更確切地說是其中的一個樣本)的輸出以及問題所在的解釋。我認為問題是某些路徑中的空格。

編輯:有您要求的樣本:

空白確實是’n’字元……

1_LecteurSy dicatio _sy dic/fiche_174.xml
2_Tra sformatio XSL_tif/fiche_174.xml
3_CorrigerTIF_cor/fiche_174.xml
4_Tra sformatio XSL_ge /fiche_174.xml

/編輯

IFS="\\n"顯然是錯誤的,因為您可以輕鬆地使用echo "\\n". 我什至不確定是否\n適用於 IFS 定義。改用 IFS=$’\n’ 或

IFS="
"

編輯

$’\n’ 形式並不能解決問題。“空白行”形式使事情看起來正確,但結果不再以列表形式呈現(每行一個)。我保留“空白行”表格,因為它的結果大致是我需要的。

/編輯

如果您在行前恢復它,設置 IFS 對我來說沒有意義for uneFiche in $i。這樣你就可以影響這條線echo $i >> "$fichier",如果引用的話會容易得多:i="$(grep -ril $1 *)",echo "$i" >> "$fichier"

編輯

i="$(grep -ril $1 *)"似乎沒有任何效果。

/編輯

如果您在空格和分詞方面遇到此類問題,那麼使用這樣的管道可能會更容易:

grep -ril --null -- "$1" * | xargs -0 /my/script.sh

/my/script.sh存在

#!/bin/bash
fichier="/home/importts/tmpCmdOpenFirst$monTerminal.xml"

for uneFiche in "$@"; do
   echo "================================"
   echo "== $uneFiche"
   echo "================================"
   echo

xmlindent "$uneFiche"

done >> "$fichier"

引用自:https://unix.stackexchange.com/questions/73901