文字列内のパスの一部を削除しようとしています。私にはパスがあります:
/path/to/file/drive/file/path/
最初の部分/path/to/file/drive
を削除して、出力を生成します。
file/path/
注:whileループには、同じ/path/to/file/drive
がすべて含まれる複数のパスがありますが、目的の文字列を削除するための「方法」を探しています。
いくつかの例を見つけましたが、それらを動作させることはできません。
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
は文字列の2番目の部分であり、明らかに間違ったことをしている...おそらくもっと簡単な方法がありますか?
POSIXシェル変数展開を使用してこれを行うこともできます。
path=/path/to/file/drive/file/path/
echo ${path#/path/to/file/drive/}
#..
部分は、変数が展開されるときに先頭の一致する文字列を取り除きます。これは、for
ループを使用している場合など、文字列が既にシェル変数にある場合に特に便利です。 %...
を使用して、変数の末尾から一致する文字列(拡張子など)を取り除くこともできます。面倒な詳細については、bash
manページを参照してください。
特定の数のパスコンポーネントを削除する場合は、-d'/'
でcut
を使用する必要があります。たとえば、path=/home/dude/some/deepish/dir
の場合:
最初の2つのコンポーネントを削除するには:
# (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
最初の2つのコンポーネントを保持するには:
$ echo $path | cut -d'/' -f-3
/home/dude
最後の2つのコンポーネントを削除するには(rev
は文字列を逆にします):
$ 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
もちろん、複数のスラッシュを一致させる場合は、sed
区切り文字を切り替える必要があります。
$ echo $path | sed 's!/some.*!!g'
/home/dude
これらの例はすべて絶対パスを使用していることに注意してください。相対パスで動作させるには、いじってみる必要があります。
削除する部分をハードコーディングしたくない場合:
$ s='/path/to/file/drive/file/path/'
$ echo ${s#$(dirname "$(dirname "$s")")/}
file/path/
Sedでこれを行う1つの方法は
echo /path/to/file/drive/file/path/ | sed 's:^/path/to/file/drive/::'
邪悪なオットーによって示唆された${path#/path/to/file/drive/}
を使用することは確かにこれを行うための典型的/最良の方法ですが、sedの提案が多数あるため、固定文字列を使用している場合はsedが過剰であることを指摘する価値があります。次のこともできます。
echo $PATH | cut -b 21-
最初の20文字を破棄します。同様に、bashで${PATH:20}
またはzshで$PATH[20,-1]
を使用できます。
パスの最初のN部分を削除する場合は、もちろん[〜#〜] n [〜#〜]を呼び出してdirname
を呼び出します glenn's answer のように、グロブを使用する方がおそらく簡単です:
path=/path/to/file/drive/file/path/
echo "${path#*/*/*/*/*/}" # file/path/
具体的には、${path#*/*/*/*/*/}
は"return $path
マイナス5つのスラッシュを含む最短プレフィックス "。
答えをハードコーディングせずに純粋なbash
basenames()
{
local d="${2}"
for ((x=0; x<"${1}"; x++)); do
d="${d%/*}"
done
echo "${2#"${d}"/}"
}