2012-06-11 8 views
31

私は文字列中のパスの一部を削除しようとしています。私は最初の部分/path/to/file/driveを除去し、出力を生成するUnixはパスの一部を削除します

/path/to/file/drive/file/path/ 

:私はパスを有する

file/path/ 

注:私はすべてに同じ/path/to/file/driveと、whileループで複数のパスを持っていますそれらの文字列を削除する方法を探しています。

私はいくつかの例を見つけたが、私はそれらを動作させることはできません。

echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:\2:' 
echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:2' 

\2文字列の第二の一部であると私は明らかに間違って何かをやっている...多分より簡単があります方法? sedのでこれを行うには

答えて

28

です。

path=/path/to/file/drive/file/path/ 
echo ${path#/path/to/file/drive/} 

#..部分は、変数が展開されたときに先頭に一致する文字列を取り除きます。 forループを使用している場合のように、文字列がすでにシェル変数に入っている場合に特に便利です。 %...を使用して、一致する文字列(拡張子など)を変数の末尾から削除することもできます。詳細については、bashのマニュアルページを参照してください。

+0

ありがとう...はい、これを実行するためにシェル変数を使用しています。両方の部分は変数で、削除する必要のある部分と完全なパスです。 – esausilva

+0

優秀!しかし、文字列が「パイプから」来ているとき、これをどのように使用できますか? – gromit190

+0

@Birger文字列がパイプから来ている場合は、シェル変数の拡張を使用するために、その変数に変数を取得する必要があります。その場合は 'sed'を使用してください。 –

9

一つの方法は、あなたはまた、これを実行するためにPOSIXシェル変数展開を使用することができます

echo /path/to/file/drive/file/path/ | sed 's:^/path/to/file/drive/::' 
+0

ありがとうございました。これはうまく動作します – esausilva

+0

素晴らしい - sed区切り文字が "/"(スラッシュ)ではなく ":"(コロン)になることは考えられませんでした。エレガントで完璧に動作します。 – stachyra

+0

あなたは一貫している限り、/と:だけでなく、sedでほとんどのデリミタを使用できます。 –

18

あなたが削除している部分をハードコーディングしたくない場合は、次の

$ s='/path/to/file/drive/file/path/' 
$ echo ${s#$(dirname "$(dirname "$s")")/} 
file/path/ 
+1

私はこれを行う方法を探して2時間を過ごしました。ハードコーディングを行わずにディレクトリ名だけを表示する方法を投稿したのはあなただけでした。私はする必要があります: 'find/path/to/file/drive/file/* _ TST -maxdepth 0 -type d'しかし、フルパスのないディレクトリの名前だけを表示したかったのです。これがそれでした。 – Whitecat

+0

@Whitecatはそれがあなたが欲しいものです。 "man find"、特に "-printf"を読んでください。 '-printf "%h \ n"'を指定することができます。これは、一致するファイルごとにディレクトリを出力するので、これを "uniq"でフィルタリングする必要があることを覚えておいてください。 –

3

${path#/path/to/file/drive/}を使用して邪悪なオットーにより示唆されるように、確かにこれを行うための典型的な/最良の方法ですが、多くのsedがあるのであなたが固定された文字列で作業しているならば、sedは残酷であることを指摘する価値があります。次のようにすることもできます。

echo $PATH | cut -b 21- 

最初の20文字を破棄します。同様に、bashには${PATH:20}、zshには$PATH[20,-1]を使用できます。

+0

ありがとうございます。私は邪悪な乙女の答えを使用しています。削除したい部分は修正されていますが、スクリプトを別のボックス/別のパスに移動すると変更される可能性があります。だから、変数の中のパスから削除したい部分を持つことは、数え切れないほど簡単になります....しかし、あなたが提供した情報は知っておくと良いです:) – esausilva

2

あなたがパスの最初のN個の部分を削除したい場合は、もちろんglenn's answerのようbasenameからN呼び出しを、使用することができますが、それはグロブを使用する方が簡単でしょう:

path=/path/to/file/drive/file/path/ 
echo "${path#*/*/*/*/*/}" # file/path/ 

具体的には、${path#*/*/*/*/*/}を意味します。返信$pathから5つのスラッシュを含む最短接頭辞「」を返します。

32

特定のNUMBER個のパスコンポーネントを削除する場合は、cut-d'/'を使用する必要があります。例えば、path=/home/dude/some/deepish/dir場合:最後の二つの成分(revは、文字列を反転)を除去する

$ echo $path | cut -d'/' -f-3 
/home/dude 

:最初の二つの成分を維持するために

# (Add 2 to the number of components to remove to get the value to pass to -f) 
$ echo $path | cut -d'/' -f4- 
some/deepish/dir 

最初の二つの成分を除去するために:

$ echo $path | rev | cut -d'/' -f4- | rev 
/home/dude/some 

最後の3つのコンポーネントエント:

$ echo $path | rev | cut -d'/' -f-3 | rev 
some/deepish/dir 

それとも、あなたはsedが働くだろう、特定のコンポーネントの前にすべてのものを削除する場合:

$ echo $path | sed 's/.*\(some\)/\1/g' 
some/deepish/dir 

または特定のコンポーネントの後:

$ echo $path | sed 's/\(dude\).*/\1/g' 
/home/dude 

それがあればさらに簡単です指定するコンポーネントを保持したくない場合は、

$ echo $path | sed 's/some.*//g' 
/home/dude/ 

そして、あなたはあまりにも最後のスラッシュを一致させることができます一致するようにしたい場合:

$ echo $path | sed 's!/some.*!!g' 
/home/dude 

:もちろん

$ echo $path | sed 's/\/some.*//g' 
/home/dude 

を使用すると、複数のスラッシュにマッチしている場合、あなたはsed区切り文字を切り替える必要がありますこれらの例はすべて絶対パスを使用しているため、それらを相対パスで動作させるために遊ぶ必要があります。

+0

驚くべき答え、特にダブル 'rev'トリック。明日の投票キャップが消えたらアップアップします。 –

+1

元のUNIXの精神で優れた、有益な答えは、{chopsquiggleSquiggle}よりずっと優れています:のみ:shellversionyoumaynaveave。 –

関連する問題