受bash中的固定链接转换

时间:2014-12-30 19:04:54

标签: regex string bash sed diacritics

我试图将用户输入转换为permlink的博客条目主题,用作URL和文件系统路径。

我设法使用:

echo 'This is a used input, containing junk!!!! öäü' | tr -dc '[:alnum:] ' | tr '[:upper:]' '[:lower:]' | tr -s ' ' '-' | sed -e 's/ö/oe/' | sed -e 's/ü/ue/' | sed -e 's/ä/ae/' | sed -e 's/ß/ss/'

输出:这是一个使用过的输入包含垃圾oau

代码绝对有用!

但是有没有更好的方法来做这个而不需要通过这么多子命令传递字符串?

要对字符串执行的任务

  • 转换为小写
  • 用" - "
  • 替换空格
  • 没有多重" - "
  • 没有特殊字符,变音符号(覆盖德语变音符号就足够了,涵盖所有内容都会加分)

4 个答案:

答案 0 :(得分:2)

看起来你是音译人物。 iconv可以处理此问题:

$ echo 'ö ä ü ß' | iconv -f utf-8 -t ascii//TRANSLIT
oe ae ue ss

这需要将您的语言区域设置为de_DE.UTF-8(或类似内容)才能获得您期望的结果(来自您的问题和个人资料,我已经做出了您正在处理的假设德语文本)。

要仅为iconv命令设置此项,请使用以下内容:

$ echo 'ö ä ü ß' | LC_ALL=de_DE.UTF-8 iconv -f utf-8 -t ascii//TRANSLIT

您也可能不使用UTF-8而是使用ISO-8859-1或ISO-8859-15;如果可能,请考虑切换到UTF-8,或相应地调整-f参数。

不幸的是,GNU tr(即Linux系统)停留在7位ASCII天(!),并且不支持转换除a到z之外的任何其他情况(它使用" xor与0x20技巧")。

由于您要将字符串转换为7位ascii,我们可以在 tr之后使用iconv ,以使其按预期工作:

echo 'ö ä ü ß' | iconv -f utf-8 -t ascii//TRANSLIT | \
    tr '[:upper:]' '[:lower:]' 

我没有看到其他2个tr调用的问题;他们都做了不同的事情。将大写转换为小写,删除重复的字符,并删除空格 将它结合在一个" smart"命令现在可能看起来不错,但对于那些必须在3年内维持它的人或者gal来说可能不太好: - )

将所有内容放在一起,并添加一些换行符,我们最终得到:

$ echo 'ö ä ü ß' | \
    iconv -f utf-8 -t ascii//TRANSLIT | \
    tr '[:upper:]' '[:lower:]' | \
    tr -dc '[:alnum:] ' | \
    tr -s ' ' '-'

答案 1 :(得分:0)

您可以将sed缩短为:

echo 'This is a used input, containing junk!!!! öäü' | tr -dc '[:alnum:] ' | tr '[:upper:]' '[:lower:]' | tr -s ' ' '-' | sed 's/ö/oe/;s/ü/ue/;s/ä/ae/;s/ß/ss/'

答案 2 :(得分:0)

假设您有以下行

This is a used input, *%$^$^%$[]             containing junk!!!! öäü  ÄÜßÖ

使用sed命令,如下所示:

sed -r 's/[ ]+/-/g;s/[^[:alnum:]-]+//g;s/-+/-/g;y/üöäÄÜÖß/uoaauob/;s/.*/\l&/g'

使用此命令尝试上述字符串

 echo 'This is a used input, *%$^$^%$[]             containing junk!!!! öäü  ÄÜßÖ' |sed -r 's/[ ]+/-/g;s/[^[:alnum:]-]+//g;s/-+/-/g;y/üöäÄÜÖß/uoaauob/;s/.*/\l&/g'

<强>结果

this-is-a-used-input-containing-junk-oau-aubo

注意:所有大写字母(包括大写的变音符号)都是小写的。

答案 3 :(得分:-1)

使用

#!/usr/bin/perl
use strict; use warnings;
use utf8;
binmode $_, ":utf8" for qw/STDOUT STDIN STDERR/;
use Text::Iconv;
my $converter = Text::Iconv->new("UTF-8", "ascii//TRANSLIT");

while (my $line = <>) {
    $line = $converter->convert($line);
    $line = lc $line;
    $line =~ s/[[:punct:]]//g;
    $line =~ s/\s/_/g;
    print $line;
}

USAGE:

echo 'This is a used input, containing JUNK!!!! öäü' | ./script.pl

输出:

this_is_a_used_input,_containing_junk_oeaeue