web-dev-qa-db-ja.com

正規表現、「/」が最後に出現した後のすべての文字を削除

ファイルに次のようなパス名のリストがあります。

/path/to/directory/one.txt
/longer/path/to/some/directory/two.py
/path/with spaces/in/it/three.sh

「/」が最後に出現した後のすべての文字を削除したいので、上記の目的の出力は次のとおりです。

/path/to/directory/
/longer/path/to/some/directory/
/path/with spaces/in/it/
3
user321546
sed 's![^/]*$!!'

これは次のことを行います。

  • 正規表現には/が含まれているため、/以外の区切り文字を使用してください。 (!|は分割線のように見えるので気に入っています。他の人は@#^、または好きなように使用します。それは/で区切られた正規表現で/を使用することは可能ですが、人にとっては読みにくい場合があります。)
  • /以外の(ゼロ以上の)文字の文字列を検索します。 (できるだけ長くしてください)。ただし、行の最後に置く必要があります。
  • そして、それを何もないものと交換します。

注意:/文字を含まない入力行は完全に消去されます(つまり、行の内容全体が削除され、空白行のみが残ります)。これを修正し、スラッシュのない行を変更せずに通過させる場合は、コマンドを次のように変更できます。

sed 's!/[^/]*$!/!'

これは、最後の/and以降のすべての文字と一致することを除いて、最初の回答と同じです、それらを/に置き換えます(実際には、最後の/を入力行に残します)。したがって、最初の回答がone.txtを見つけて何も置き換えない場合、/one.txtを見つけて/に置き換えます。ただし、/文字を含まない行では、最初の回答は行全体と一致し、何も置換されませんが、これは一致を見つけられないため、置換されません。

このコマンドの区切り文字として/を使用できますが、その場合は

sed 's/\/[^/]*$/\//'

正規表現の一部であるスラッシュと置換文字列の前にback slashes(\)を付けることで、スラッシュを「エスケープ」します。一部の人々は、この「木を傾ける」ジャングルを読み、維持するのが難しいと感じますが、基本的にはスタイルの問題に帰着します。

1
Scott

dirnameユーティリティを使用できます。

xargs -I {} dirname {} <file.txt

これにより、リスト内の各親ディレクトリのパス名がわかります。与えられたリストについては、

/path/to/directory
/longer/path/to/some/directory
/path/with spaces/in/it

パスに改行を埋め込むには、

/some/path with a \
newline/in/it

引用符を埋め込むには、次のようにエスケープします。 \"

0
Kusalananda