2017-02-16 22 views
1

我試圖給grep一個路徑字符串,裏面的內容都是雙引號。 For循環通過test.txt文件,它搜索new1.xml進行匹配。如果找到,它會在路徑中打印出一個字符串。grep一個雙引號內的字符串

預期輸出

abc/test/test 
abc/test/test 
cd/test1/test2 
cdf 

的test.txt

test/test 
test/test 
test1/test2 
test1 

new1.xml

<abc name="test/test" path="abc/test/test" /> 
<abc name="test/test1" path="abc/test/test1" /> 
<abc name="test1/test2" path="cd/test1/test2" /> 
<path="cdf" name="test1" /> 

腳本

for f in test.txt 
    do 
    echo "Processing $f" 
     paste $f | while read lines; do 
      results=`cat new1.xml | grep -o "name.*$lines.*" | grep -o 'path.*' | sed 's/[^"]*"\([^"]*\)".*/\1/'` 
     done 
    done 

輸出

abc/test/test 
abc/test/test1 
+0

什麼是懸掛'if'在你做的循環? – codeforester

回答

1

可以有效地寫你的循環多一點,並使用sed而不是多個grep s到得到你想要的東西:

for f in test.txt; do 
    echo "Processing $f" 
    while read line; do 
    grep 'name="'$line'"' new1.xml 
    done < "$f" | sed -E 's/.+path="([^"]+)".+/\1/' 
done 

對於您的示例,上面的腳本給出了此輸出:

Processing test.txt 
abc/test/test 

如果你只是處理一個文件,你不需要外循環:

while read line; do 
    grep 'name="'$line'"' new1.xml 
    done < "test.txt" | sed -E 's/.+path="([^"]+)".+/\1/' 
+1

如果你將管道sed到循環外,你只需調用sed一次而不是每行一次。 –

+0

你是對的@BenjaminW。 - 只是修改了答案。 – codeforester

+0

非常感謝codeforester和BenjaminW,你們兩個都是救星。 :) – Mihir

1

在你的代碼,如果你調整的最後部分:

....|grep -o 'path=\".*\"' |sed 's/[^"]*"\([^"]*\)".*/\1/' 

應該工作。我沒有測試你的整個代碼,只有grep + sed。

另外我可以看到sed命令周圍有一些反引號。如果是這樣,他們需要被刪除。

在我的測試這個工作:

echo -e "<abc name="test/test" path=\"abc/test/test\" />" |grep -o 'path=\".*\"' |sed 's/[^"]*"\([^"]*\)".*/\1/' 
abc/test/test 

的另一種方法來隔離你需要什麼沒有一個循環,但用一個命令將

grep -F -f test.txt new1.xml |grep -o 'path=\".*\"' |sed 's/[^"]*"\([^"]*\)".*/\1/' #or a simpler sed like |sed 's/path=//; s/\"//g' 

的grep -F:尋找固定的字符串從文件加載模式

另一種替代方法::未正則表達式
-f

echo -e "<abc name="test/test" path=\"abc/test/test\" />" |sed -e 's/^.*path=\"//; s/\" .*$//g' 
#in your case: 
grep -F -f test.txt new1.xml |sed -e 's/^.*path=\"//; s/\" .*$//' 

更新:測試用一行代碼:

$ cat file3 
test/test 
test/test 
test1/test2 
test1 

$ cat file4 
<abc name="test/test" path="abc/test/test" /> 
<abc name="test/testsdk" path="abc/test/testsdk" /> 
<abc name="test/test" path="abc2/test/test" /> 
<abc name="test1/test2" path="ggg/test1/test2" /> 
<abc name="test2/test2" path="vvv/test2/test2" /> 
<path="cdf" name="test1" /> 

$ grep -F -f file3 file4 |sed 's/^.*path=//; s/\"//g; s/ .*$//g' 
abc/test/test 
abc/test/testsdk 
abc2/test/test 
ggg/test1/test2 
cdf 
+0

非常感謝喬治只是一個很好的解釋。 – Mihir

+0

hello @George,如果test.txt具有「test/test」副本,則單個命令僅打印一個結果。這是刪除重複。有什麼方法可以打印重複的東西? – Mihir

+0

@Mhhir文件test.txt保留模式。重複模式沒有意義。grep將使用第一個模式來匹配xml文件中的所有事件。如果xml文件具有不同的條目,但是在相同的模式下,例如'',則單行命令也會捕獲這些條目。在我的答案中查看我機器上的測試。 –