Sehr seltsames Verhalten mit grep und IFS

Sehr seltsames Verhalten mit grep und IFS

Ich habe Probleme bei der Verwendung von grep, die zurückgegebenen Ergebnisse sind „n-leer“, also ohne das Zeichen „n“ …

Dies ist das Skriptbeispiel:

OLDIFS=$IFS
IFS="\\n"

i=$(grep -ril $1 *)

echo $i

IFS=$OLDIFS

Ich habe es mit IFS='\n'und versucht IFS="\n", aber das Ergebnis zeigt die richtigen Pfade annurwenn ich das IFS loswerde...

Ich verwende das Ergebnis in einer for theFile in $i; do......doneSchleife, wobeidie Ergebnisse richtig genutzt und theFilekorrekt dargestellt werden.

Das einzige Problem ist, dass ich keine korrekte Konsolen-/Dateiausgabe von habe $i, was strategische Daten sind:

Was ich in der Konsole sehe und in der geschriebenen Datei (Beispiel):

LecteurSy dicatio _sy dic/fiche_93.xml

Was angezeigt und geschrieben werden soll (Beispiel):

LecteurSyndication_syndic/fiche_93.xml

Irgendeine Idee ?

EDIT: vollständiges Skript zum Abspielen zu Hause ;)

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

Antwort1

Es ist nicht einfach, Ihrer Problembeschreibung zu folgen. Die einzige nützliche Information fehlt, nämlich die Ausgabe grep -ril $1 *(oder vielmehr ein Beispiel davon) und eine Erklärung, worin das Problem besteht. Ich gehe davon aus, dass das Problem in einigen Pfaden Leerzeichen sind.

BEARBEITEN: Hier ist das von Ihnen angeforderte Beispiel:

Bei den Leerzeichen handelt es sich tatsächlich um N-Zeichen ...

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

/BEARBEITEN

IFS="\\n"ist offensichtlich falsch, wie Sie leicht mit überprüfen können echo "\\n". Ich bin mir nicht einmal sicher, ob \nes in der IFS-Definition funktioniert. Verwenden Sie stattdessen IFS=$'\n' oder

IFS="
"

BEARBEITEN

Die Form $'\n' löst das Problem nicht. Die Form „Leerzeile“ lässt die Dinge zwar richtig erscheinen, aber die Ergebnisse werden nicht mehr als Liste (eines pro Zeile) angezeigt. Ich behalte die Form „Leerzeile“, da ihr Ergebnis ungefähr dem entspricht, was ich brauche.

/BEARBEITEN

Das Setzen von IFS macht für mich keinen Sinn, wenn man es vor der for uneFiche in $iZeile wiederherstellt. Auf diese Weise beeinflusst man nur die Zeile echo $i >> "$fichier"und das wäre viel einfacher gewesen, wenn man zitiert hätte: i="$(grep -ril $1 *)",echo "$i" >> "$fichier"

BEARBEITEN

i="$(grep -ril $1 *)"scheint keine Wirkung zu haben.

/BEARBEITEN

Wenn Sie solche Probleme mit Leerzeichen und Worttrennung haben, ist es möglicherweise einfacher, mit einer Pipeline wie dieser zu arbeiten:

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

mit dem /my/script.shSein

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

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

xmlindent "$uneFiche"

done >> "$fichier"

Antwort2

Erstens haben Sie IFSauf gesetzt \n, nicht auf eine neue Zeile. In Bash können Sie verwenden, $'…'um Backslash-Sequenzen als Steuerzeichen interpretieren zu lassen:

IFS=$'\n'

Oder Sie haben die portable Option, einen wörtlichen Zeilenumbruch zu verwenden.

IFS='
'

Das zweite Problem ist, dass IFSes darauf ankommt, wann Sie eine Variable erweitern. Sie muss also festgelegt werden, wenn $ierweitert wird. Es spielt eigentlich keine Rolle, wann Sie festlegen 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"

Vergessen Sie außerdem nicht, Variablen in Anführungszeichen zu setzen, wenn Sie nicht teilen, z. B. das Muster, das Sie an übergeben grep. Falls das Muster mit beginnt -, übergeben Sie es grepmit der -eOption an. Setzen Sie es auch --vor die Dateinamen, falls der erste Dateiname mit beginnt -. Falls ein Dateiname Glob-Zeichen enthält, deaktivieren Sie das Globbing mit , set -fbevor Sie eine Variablenerweiterung ohne Anführungszeichen lassen.

Ein einfacherer Ansatz wäre, grepjede Datei innerhalb der Schleife aufzurufen. Ein zusätzlicher Vorteil wäre, dass Ihr Skript bei Dateinamen mit Zeilenumbrüchen nicht abstürzt.

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

Antwort3

Hier ist das endgültige Skript, das dank Gilles funktioniert:

#!/bin/bash

# use a buffer file per terminal, permits multiple users
monTerminal=$(tty) ; monTerminal=${monTerminal:9}
fichier="........./tmpCmdFiche$monTerminal.xml"

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

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

i=$(grep -ril -e "$1" -- *)

set -f
OLDIFS="$IFS"
IFS='
'

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

echo "$i" >> "$fichier"

for uneFiche in $i; do

set +f; IFS="$OLDIFS"

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

xmlindent "$uneFiche" >> "$fichier"

done < ............/tmpCmdOpenFirst_liste.txt

set +f
IFS="$OLDIFS"

Und dann ein Beispiel für das cmdFiche somethingsosearchBefehlsergebnis:

== Recherche dans les fiches  ==
Recherche : somethingsosearch
Dans      : ............/XMLs/.........
== Liste des fichiers trouves ==
1_ImportationZip_zip/file2.xml
2_ImportationSuppSyndication_syndic/file19.xml
3_ModifierOrdreImages_ordre/fiche_44.xml
4_CorrigerPeriodesViaSyndication_periodes/fiche_44.xml
5_TransformationXSL_tif/fiche_44.xml
6_CorrigerRaisonSocialeViaSyndic_raisonsociale/fiche_44.xml
7_ExclureImportNoeuds_avantv2/fiche_44.xml
================================
== 1_ImportationZip_zip/file2.xml
================================

<?xml version="1.0" encoding="utf-8"?>

<tif:OI xmlns:tif="http://www.tourinfrance.net/Tourinfrance3/" xmlns:xsi="http://www.w$

    <!--Granule DublinCore-->

    <tif:DublinCore>

Eindrucksvoll !

verwandte Informationen