0

我有文本文件:

/path/to/delete/dir1/dir2/dir3/file1.ext
/path/to/delete/dir1/dir2/dir3/file2.ext
/path/to/delete/dir1/dir2/dir3/file3.ext

我想复制每个字符串并进行一些替换以得到这个:

dir1/dir2/dir3/file1.ext dir1-dir2-dir3/file1.ext
dir1/dir2/dir3/file2.ext dir1-dir2-dir3/file2.ext
dir1/dir2/dir3/file3.ext dir1-dir2-dir3/file3.ext

我制作了脚本,删除了前导路径和重复的字符串:

sed -e 's/\/path\/to\/delete\///' -e 's/.\+/\0 \0/'  list.txt

现在我得到了这个:

dir1/dir2/dir3/file1.ext dir1/dir2/dir3/file1.ext
dir1/dir2/dir3/file2.ext dir1/dir2/dir3/file2.ext
dir1/dir2/dir3/file3.ext dir1/dir2/dir3/file3.ext

但是不知道在空格后替换斜杠。

4

8 回答 8

3

这可能对您有用(GNU sed):

sed -r 's|/path/to/delete/(.*)|\1 \1|;:a;s|/([^ /]*/[^ /]*)$|-\1|;ta' file

删除 require 模式,然后复制字符串。

/通过第二个字符串向后工作,用.替换除最后一个之外的所有字符串-

于 2013-06-12T06:18:53.080 回答
2

使用保持空间:

sed -e 's%/path/to/delete/%%;h;s%/%-%g;x;G;s/\n/ /'

h模式空间(删除前导路径后的名称)复制到保留空间。将模式空间中的斜线替换为破折号。交换 ( x) 模式并保留空格。将模式空间后的保留空间与换行符 ( G) 连接起来。用空格替换换行符。

这取代了太多的斜线......但如果你也知道分支的话,这种变化是“微不足道的” sed

sed -e 's%/path/to/delete/%%;h;: redo;s%/\(.*/.*\)%-\1%g;t redo;x;G;s/\n/ /'

不同之处在于它的存在: redo创建了一个标签redo;如果替代操作自上次测试以来发生了任何更改,则t redo跳转到标签;redo在更复杂的正则表达式中,它匹配一个斜杠(不被记住),然后是任何包含斜杠(被记住)的材料。未记住的斜线由破折号代替。可以省略冒号后面的空格,也可以省略 . 后面的空格t。我不相信这样做是个好习惯。我可能还会将其拆分为单独的命令以使其更易于理解:

sed -e 's%/path/to/delete/%%' \
    -e 'h' \
    -e ': redo' \
    -e 's%/\(.*/.*\)%-\1%g' \
    -e 't redo' \
    -e 'x' \
    -e 'G' \
    -e 's/\n/ /'

或者:

sed -e 's%/path/to/delete/%%
        h
        : redo
        s%/\(.*/.*\)%-\1%g
        t redo
        x
        G
        s/\n/ /'
于 2013-06-11T23:37:37.277 回答
2

Perl 解决方案:

perl -ne 'chomp; s%/path/to/delete/%%; print "$_ "; s%/%-% while 1 < y=/==; print "$_\n";'

它只是不断替换/-足够的斜线。它还可以与第二个副本分开工作,以使工作更轻松。

于 2013-06-11T23:37:45.470 回答
2

awk

script.awk 的内容:

BEGIN {
    FS="/"
}
{
    for (i=5;i<NF;i++) {
        printf "%s/" ,$i
    }
    printf "%s " ,$NF
}
{
    for (i=5;i<NF-1;i++) {
        printf "%s-", $i
    }
    printf "%s/%s\n" ,$(NF-1),$NF
}

测试:

$ cat file
/path/to/delete/dir1/dir2/dir3/file1.ext
/path/to/delete/dir1/dir2/dir3/file2.ext
/path/to/delete/dir1/dir2/dir3/file3.ext
$ awk -f script.awk file
dir1/dir2/dir3/file1.ext dir1-dir2-dir3/file1.ext
dir1/dir2/dir3/file2.ext dir1-dir2-dir3/file2.ext
dir1/dir2/dir3/file3.ext dir1-dir2-dir3/file3.ext

gawk

$ gawk '{
    printf ("%s ", gensub(/\/path\/to\/delete\//,"","G",$0)); 
    printf ("%s\n", gensub(/\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)/,"\\4-\\5-\\6\/\\7","G",$0))
}' file

测试:

gawk '{printf ("%s ", gensub(/\/path\/to\/delete\//,"","G",$0)); printf "%s\n", gensub(/\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)\/(.*)/,"\\4-\\5-\\6\/\\7","G",$0) }' file
dir1/dir2/dir3/file1.ext dir1-dir2-dir3/file1.ext
dir1/dir2/dir3/file2.ext dir1-dir2-dir3/file2.ext
dir1/dir2/dir3/file3.ext dir1-dir2-dir3/file3.ext
于 2013-06-12T00:54:47.623 回答
1

I suppose it's a bit of a dirty hack, but it's simple as simple as you can get with sed and should be just enough for your task:

$ sed -r -e 's@/path/to/delete/@@; h; s@(.+)/(.*)@\1\n\2@; s@/@-@g; s@(.+)\n(.+)@\1/\2@; x; G; s/\n/ /' list.txt
dir1/dir2/dir3/file1.ext dir1-dir2-dir3/file1.ext
dir1/dir2/dir3/file2.ext dir1-dir2-dir3/file2.ext
dir1/dir2/dir3/file3.ext dir1-dir2-dir3/file3.ext
于 2013-06-11T23:56:12.083 回答
1

另一个 bash 解决方案

while read path; do
    path=${path#/path/to/delete/}
    file=${path##*/}
    dir=${path%/*}
    printf "%s %s/%s\n" "$path" "${dir//\//-}" "$file"
done < filename
于 2013-06-12T01:34:14.333 回答
1

GNU sed(无跳转)

sed -r 's./path/to/delete/..;h;s./([^/]*)$.|\1.;s./.-.g;s.\|./.;x;G;s/\n/ /' file
于 2013-06-12T07:19:22.563 回答
0

仅使用 bash 的解决方案:

dirname使用and将路径拆分为目录和文件名basename,使用 将目录路径中的斜杠更改为破折号tr,然后连接结果。

➤ for f in "dir1/dir2/dir3/file1.ext" "dir1/dir2/dir3/file1.ext" "dir1/dir2/dir3/file2.ext" "dir1/dir2/dir3/file2.ext"; 
do 
   echo "$(dirname $f | tr '/' '-')/$(basename $f)" ; 
done
dir1-dir2-dir3/file1.ext
dir1-dir2-dir3/file1.ext
dir1-dir2-dir3/file2.ext
dir1-dir2-dir3/file2.ext

有时,您需要的不是锤子。

于 2013-06-12T00:36:36.867 回答