2010-02-13 147 views
5

我正在使用 sed -e "s/\*DIVIDER\*/$DIVIDER/g"用用戶指定的字符串替換*DIVIDER*,該字符串存儲在$DIVIDER中。問題是我希望它們能夠將轉義字符指定爲分隔符,如\ n或\ t。當我嘗試這個時,我最後只是寫了字母n或t,等等。使用sed將變量的內容替換爲字符串,即使它是轉義字符

有沒有人有關於如何做到這一點的任何想法?這將不勝感激!

編輯:這是腳本的肉,我必須缺少的東西。

curl --silent "$URL" > tweets.txt 

if [[ `cat tweets.txt` == *\<error\>* ]]; then 
    grep -E '(error>)' tweets.txt | \ 
    sed -e 's/<error>//' -e 's/<\/error>//' | 
    sed -e 's/<[^>]*>//g' | 

head $headarg | sed G | fmt 

else 
    echo $REPLACE | awk '{gsub(".", "\\\\&");print}' 
    grep -E '(description>)' tweets.txt | \ 
    sed -n '2,$p' | \ 
    sed -e 's/<description>//' -e 's/<\/description>//' | 
    sed -e 's/<[^>]*>//g' | 
    sed -e 's/\&amp\;/\&/g' | 
    sed -e 's/\&lt\;/\</g' | 
    sed -e 's/\&gt\;/\>/g' | 
    sed -e 's/\&quot\;/\"/g' | 
    sed -e 's/\&....\;/\?/g' | 
    sed -e 's/\&.....\;/\?/g' | 
    sed -e 's/^ *//g' | 
    sed -e :a -e '$!N;s/\n/\*DIVIDER\*/;ta' | # Replace newlines with *divider*. 
    sed -e "s/\*DIVIDER\*/${DIVIDER//\\/\\\\}/g" |   # Replace *DIVIDER* with the actual divider. 

    head $headarg | sed G 
fi 

sed的線的長列表中從XML源替換字符,並且最後兩個是應該與指定的字符,以取代換行符的那些。我知道用另一個換行符替換換行符似乎是多餘的,但這是我能想到的最簡單的方法,讓他們選擇他們自己的分頻器。分區替換對於普通字符非常有用。

+4

你的腳本寫的不好。很多不必要的sed步驟。顯示你正在處理的輸入文件,並顯示你想要的輸出。 – ghostdog74 2010-02-13 18:00:30

回答

7

您可以使用bash逃脫這樣的反斜線:

sed -e "s/\*DIVIDER\*/${DIVIDER//\\/\\\\}/g" 

的語法是${name/pattern/string}。如果模式以/開始,則name中的pattern的每個發生都被替換爲string。否則只會替換第一個事件。

+0

用這個,我最終得到一個雙反斜槓和一個插入到流中的「n」。也許這是我處理事物的方式。我將編輯原始帖子以包含更多的腳本。 – vilhalmer 2010-02-13 16:16:22

+1

tangens的解決方案處理反斜槓,但不是\ n或\ t。問題是sed不能識別\ n或\ t。您可以將它們明確地放在DIVIDER中,或者通過另一個過濾器來管理輸出以用換行符替換\ n。例如:sed's/\\ n/\ /g' – 2010-02-13 17:13:51

+0

這是一個好主意,我可以通過tr將它返回。謝謝! – vilhalmer 2010-02-14 12:29:32

0

你只需要逃避逃逸字符。

\ n將匹配\ n

\將匹配\

\\將匹配\

+0

我剛剛嘗試過\ n並且它最終成了\ n,但它直接打印出來。我如何讓sed將它解釋爲一個轉義而不是普通的字符串? – vilhalmer 2010-02-13 15:47:12

1

可能:

case "$DIVIDER" in 
(*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');; 
esac 

我打了這個腳本:

In: <<xx\n>> 
Out: <<xx\\n>> 
In: <<xxx\\ddd>> 
Out: <<xxx\\\\ddd>> 
In: <<xxx>> 
Out: <<xxx>> 

與在MacOS X '的ksh' 或 '慶典'(而不是 '上海')
for DIVIDER in 'xx\n' 'xxx\\ddd' "xxx" 
do 
    echo "In: <<$DIVIDER>>" 
    case "$DIVIDER" in  (*\\*) DIVIDER=$(echo "$DIVIDER" | sed 's/\\/\\\\/g');; 
    esac 
    echo "Out: <<$DIVIDER>>" 
done 

運行

1

它似乎是一個簡單的替代:

$ d='\n' 
$ echo "a*DIVIDER*b" | sed "s/\*DIVIDER\*/$d/" 
a 
b 

也許我不明白你想完成什麼。

那麼也許這一步可能採取的地方過去兩年你的:

sed -n ":a;$ {s/\n/$DIVIDER/g;p;b};N;ba" 

注意美元符號後的空間。它阻止shell將「$ {s ...」解釋爲變量名稱。

而作爲ghostdog74建議,你有太多的電話sed。您可以將大量管道字符更改爲反斜槓(續行),並刪除除第一個之外的所有「sed」(到處留下「-e」)。(未經測試)

+0

感謝有關不必要的seds調用的信息!我不久前寫了這篇文章,並且對一般的sed或shell腳本知之甚少。 – vilhalmer 2010-02-14 12:32:17

+0

我已經嘗試將持續和所有在一條線上的調用結合起來,但一些替代品停止工作。它不再刪除標籤或額外的空間。他們需要進入一些神奇的秩序嗎? – vilhalmer 2010-02-14 13:26:28

+0

你有沒有離開這個地方? 'sed -n'2,$ p'| sed ...'你正在選擇要採取行動的線路。如果你在這裏取出管道,它可能不起作用。沒有看到數據和你的修改腳本,我不能肯定地說。你應該知道,這種方式瘋狂謊言(在HTML上使用正則表達式):http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – 2010-02-14 15:04:46

0

中使用FreeBSD的sed(例如,在Mac OS X),你必須預處理$分頻器用戶輸入:

d='\n' 
d='\t' 
NL=$'\\\n' 
TAB=$'\\\t' 
d="${d/\\n/${NL}}" 
d="${d/\\t/${TAB}}" 
echo "a*DIVIDER*b" | sed -E -e "s/\*DIVIDER\*/${d}/"