2011-01-30 56 views
10

我已經申請Unix命令一個字符串(可以包含#,/,&,@和所有其他的sed!? !?caracters),它可以包含所有類型的字符(&的,|,/,...)sed的稀土分隔符(不是和其他?|/...)

它是一個複雜的分隔符(帶有兩個caracters),它可以許可證outpass錯誤:

sed: -e expression #1, char 22: unknown option to `s' 

在此先感謝

+0

至少,向我們展示您給sed導致錯誤的字符串。 – 2011-01-30 19:14:41

+0

在sed中傳遞的字符串可以包含#,!,/,?,&,@和所有其他字符 – Unitech 2011-01-30 19:20:50

回答

1

在sed中沒有這種多字符表達式分隔符的選項,但是我懷疑你需要這樣的 。分隔符不應出現在模式中,但是如果它出現在正在處理的字符串中,則不會出現問題。除非你做了一件非常奇怪的事情,否則總會有一些角色沒有出現在你的搜索模式中,可以作爲分隔符。

+0

我正在做一件非常奇怪的事情,是的。我正在測試所有類型的字符。 – Unitech 2011-01-30 19:22:26

+0

@tknew:只有Perl但不是sed提供獨立於分隔符的匹配。由於Perl是sed的一個適當的超集,這可能就足夠了。 – tchrist 2011-01-30 19:33:24

+0

有一天我遇到了這個問題,我不認爲我在做什麼是非常奇怪的:我試圖刪除包含任意字符串「$ STR」的行,例如, `sed -i -e'/'「$ STR」'/ d'$ FILE`。或者上面有更好的成語嗎? – 2011-02-11 06:30:41

11

輸入文件中的字符無關緊要 - sed可以很好地解析它們。但是,如果您的圖案中包含大多數常見字符,或者您的圖案可能未預先知道,則可能有問題。

至少在GNU sed上,可以使用非常不可能的非可打印字符作爲分隔符存在於您的模式中。例如,如果你的shell是Bash

$ echo '|||' | sed s$'\001''|'$'\001''/'$'\001''g' 

在這個例子中,猛砸replaces$'\001'與具有八進制值001字符 - 在ASCII它的SOH字符(標題的開始)。

由於這些字符是控制/不可打印的字符,所以它們存在於模式中是值得懷疑的。除非你正在做一些奇怪的事情,比如修改二進制文件 - 或者沒有正確的區域設置的Unicode文件。

1

您需要Perl提供的嵌套分隔符設施。這允許使用諸如匹配,替換和音譯等內容,而不用擔心內容中包含分隔符。由於perl是sed的超集,因此無論您使用sed爲何,您都應該可以使用它。

考慮一下:

$ perl -nle 'print if /something/' inputs 

現在,如果你something包含一個斜線,你有問題。解決這個問題的方法是更改​​分隔符,最好是更改分隔符。因此,例如,你可以有任何你無論在什麼(提供的backets是平衡的)shell變量的$,它獲取由外殼插喜歡之前的Perl甚至被稱爲在這裏:

$ perl -nle "print if m($WHATEVER)" /usr/share/dict/words 

即使你有工作正確嵌套在$ WHATEVER中的parens。在Perl中正確嵌套的四個包圍對是< >,(),[ ]{ }。如果分隔符是平衡的,它們允許包含分隔符的任意內容。

如果是不是平衡,那麼根本不要使用分隔符。如果模式是一個Perl的變量,你不需要使用匹配運營商提供使用=~運營商,所以:

$whatever = "some arbitrary string (/ # [ etc"; 
if ($line =~ $whatever) { ... } 
1

與吉姆·劉易斯的幫助下,我終於用SED之前做了一個測試:

if [ `echo $1 | grep '|'` ]; then 
    grep ".*$1.*:" $DB_FILE | sed "[email protected]^.*$1*.*\(:\)@@ " 
else 
    grep ".*$1.*:" $DB_FILE | sed "s|^.*$1*.*\(:\)|| " 
fi 

感謝您的幫助

0

哇。我完全不知道你可以使用任何字符作爲分隔符。 至少有一半時間我使用sed和BRE在路徑上,代碼片段,垃圾字符,類似的東西。我最終得到了一堆可怕的難以理解的逃跑,我甚至不確定不會死在我沒有想到的某種組合上。但是,如果你可以排除只是一些字符類(甚至只是一個字符)

echo '#01Y $#1+!' | sed -e 'sa$#1+ashita' -e 'su#01YuHolyug'

> > > Holy shit! 這是所以容易得多。

1

另一種方法是使用Shell參數替換。

${parameter/pattern/replace} # substitute replace for pattern once 

${parameter//pattern/replace} # substitute replace for pattern everywhere 

這裏是一個相當複雜的例子是難以與SED:

$ parameter="Common sed delimiters: [sed-del]" 
$ pattern="\[sed-del\]" 
$ replace="[/_%:\\@]" 
$ echo "${parameter//$pattern/replace}" 

結果是:

Common sed delimiters: [/_%:\@] 

然而:這隻適用於bash參數,而不適用於sed擅長的文件。

0

轉義BASH解析內聯分隔符很麻煩,也很難閱讀(儘管分隔符在第一次使用per-expression時需要避開sed的好處)。

要齊心協力thkala的答案,user4401178的評論:

DELIM=$(echo -en "\001"); 
sed -n "\\${DELIM}${STARTING_SEARCH_TERM}${DELIM},\\${DELIM}${ENDING_SEARCH_TERM}${DELIM}p" "${FILE}" 

此示例返回所有結果從${STARTING_SEARCH_TERM}開始直到${ENDING_SEARCH_TERM}不字符與ASCII碼匹配SOH(稅號的開始) 001.

相關問題