例子

例子

我想对文件中的 url 列表(1 个 url/行)进行排序,这样如果 url 以www.or开头m.,则排序是在假设该部分不存在(或与排序无关)的情况下完成的。有什么建议么?

例子

facebook.com###page
fahrrad.de###userlike-popup
m.facebook.com##.cx
www.facebook.com##body
www.fahrrad.de###userlike-footerbar

排序后的文件如下所示

www.facebook.com##body
m.facebook.com##.cx
facebook.com###page
www.fahrrad.de###userlike-footerbar
fahrrad.de###userlike-popup

解释

  • facebook.com优先fahrrad.de于 c 在 h 之前
  • www.facebook.com##bodym.facebook.com##.cx如同b之前一样先于.
  • m.facebook.com##.cxfacebook.com###page如同.之前一样先于#
  • www.fahrrad.de###userlike-footerbar优先fahrrad.de###userlike-popup于 f 位于 p 之前

答案1

您始终可以在要跳过的部分之后添加一个字符并从那里开始排序(然后删除该字符):

如果您sed支持该-E选项(最新版本的 GNUsed会这样做,而旧版本会替代-r,尽管这对非 GNU 实现的移植性较差):

<file sed -E 's/^(www\.|m\.)?/&:/' | sort -t: -k2 | sed 's/://'

awk可移植的是,您可以使用or执行相同的操作perl

<file awk '{sub(/^(www\.|m\.)?/, "&:"); print}' | sort -t: -k2 | sed 's/://'
<file perl -pe 's/^(www\.|m\.)?/$&:/' | sort -t: -k2 | sed 's/://'

虽然使用 POSIX sed,你总是可以这样做:

<file sed -e 's/^www\./&:/;t' -e 's/^m\./&:/;t' -e 's/^/:/' |
  sort -t: -k2 | sed 's/://'

或者,您可以在不以Nor.开头的行的开头添加 a ,并对第一个后面的部分进行排序:www.m..

<file sed -e '/^www\./b' -e '/^m\./!s/^/./' | sort -t. -k2 | sed 's/^\.//'

答案2

单独使用perl

perl -e 'print sort {$a=~s/^(www|m)\.//r cmp $b=~s/^(www|m)\.//r} <>'

$a$b是 Perl 中的特殊变量,允许指定自定义sort比较

s/^(www|m)\.//r将在应用之前从输入行中删除前导www.或部分m.sort

<>在这种情况下将给出输入行数组

施瓦茨变换变体:

perl -e 'print map { $_->[0] }
         sort { $a->[1] cmp $b->[1] or $a->[0] cmp $b->[0] }
         map { [$_, s/^(www|m)\.//r] } <>'

同样,与ruby

# can golf it to {_1.sub(/^(www|m)\./, "")} on latest version
ruby -e 'puts readlines.sort_by {|s| s.sub(/^(www|m)\./, "")}'

答案3

让我们看看这个:

sed 's;^\([wm\.]*\)\(.*\)$;\2 \1\2;' file | sort | awk '{ print $2 }'

相关内容