admin管理员组

文章数量:1122832

This basically boils down to "How do I combine pwd and sed delete (or alternative)". Given a file with a list of file paths, how do I delete lines which contain my current directory?

So, if file1 contains:

/dirA/subdir1/somefile
/dirB/subdir2/somefile
/dirB/subdir2/somefile
/dirC/subdir2/somefile
/dirD/subdir1/somefile

And my working directory is:

/dirB/subdir2/

Then my output should edit file1 in place to result in:

/dirA/subdir1/somefile
/dirC/subdir2/somefile
/dirD/subdir1/somefile

I know that I can delete lines with:

sed '/pattern to match/d' file1

And I can feed pwd into sed like so:

sed 's?#REPLACE-WITH-PATH?'`pwd`'?'

So I thought I could combine them as one of the following:

sed '/'`pwd`'/d' file1
sed '?'`pwd`'?d' file1
sed '#'`pwd`'#d' file1

The first option won't read properly, because it interprets the slashes of the path as part of the sed command. The second doesn't recognize the question mark. The third runs, but doesn't do anything.

This basically boils down to "How do I combine pwd and sed delete (or alternative)". Given a file with a list of file paths, how do I delete lines which contain my current directory?

So, if file1 contains:

/dirA/subdir1/somefile
/dirB/subdir2/somefile
/dirB/subdir2/somefile
/dirC/subdir2/somefile
/dirD/subdir1/somefile

And my working directory is:

/dirB/subdir2/

Then my output should edit file1 in place to result in:

/dirA/subdir1/somefile
/dirC/subdir2/somefile
/dirD/subdir1/somefile

I know that I can delete lines with:

sed '/pattern to match/d' file1

And I can feed pwd into sed like so:

sed 's?#REPLACE-WITH-PATH?'`pwd`'?'

So I thought I could combine them as one of the following:

sed '/'`pwd`'/d' file1
sed '?'`pwd`'?d' file1
sed '#'`pwd`'#d' file1

The first option won't read properly, because it interprets the slashes of the path as part of the sed command. The second doesn't recognize the question mark. The third runs, but doesn't do anything.

Share Improve this question edited yesterday Timur Shtatland 12.3k2 gold badges37 silver badges61 bronze badges asked yesterday David RobieDavid Robie 4213 silver badges10 bronze badges 8
  • You can use grep -v $PWD as an alternative. – Yuri Ginsburg Commented yesterday
  • 1 How should symlinks in path be handled? For example, if /bin is a symlink to /usr/bin and you cd /bin, do you expect pwd to give /bin or /usr/bin ? – jhnc Commented yesterday
  • 1 can your paths contain regex metacharacters? (eg. ., ?, *, [, etc) – jhnc Commented yesterday
  • 1 What do you want to do with lines that contain a subdirectory of the current working directory, for example /dirB/subdir2/subdir3/somefile? – Timur Shtatland Commented yesterday
  • 1 @TimurShtatland Great question! Based on the way I'm doing this, file1 will actually never see anything below its directory. – David Robie Commented 21 hours ago
 |  Show 3 more comments

3 Answers 3

Reset to default 3

Because your current directory contains / I suggest to switch from /.../d to \|...|d or \#...#d .

The variable $PWD is filled with the current working directory, so append a slash to it and use awk.

# Solution improved/replaced with the comment of jhnc
awk 'index($0,ENVIRON["PWD"]"/")!=1' file1

Use one of the following Perl one-liners, depending on whether you want to skip or print the lines that contain a subdirectory of the current working directory, for example /dirB/subdir2/subdir3/somefile:

Skip /dirB/subdir2/subdir3/somefile:

perl -lne 'next if m{ ^ \Q$ENV{PWD}\E / .+ $ }x; print; ' file1

Print /dirB/subdir2/subdir3/somefile:

perl -lne 'next if m{ ^ \Q$ENV{PWD}\E / [^/]+ $ }x; print; ' file1

The Perl one-liner uses these command line flags:
-e : Tells Perl to look for code in-line, instead of in a file.
-n : Loop over the input one line at a time, assigning it to $_ by default.
-l : Strip the input line separator ("\n" on *NIX by default) before executing the code in-line, and append it when printing.

The regex uses these modifier:
x : Ignore whitespace and comments, for readability.

In the regex:
^ : Matches the beginning of the line.
\Q$ENV{PWD}\E : Current working directory ($ENV{PWD}), with pattern metacharacters disabled (quoted). Thanks to jhnc for the suggestion to use \Q.
.+ : Any character repeated 1 or more times.
[^/]+ : Any character except a slash (/), repeated 1 or more times.
$ : Matches the end of the line.

See also:

  • perldoc perlrun: how to execute the Perl interpreter: command line switches
  • perldoc perlre: Perl regular expressions (regexes)
  • perldoc perlrequick: Perl regular expressions quick start

本文标签: regexDelete lines in file if they contain current working directoryStack Overflow