命令 tr 是否能够将字符翻译成更长的字符串?

命令 tr 是否能够将字符翻译成更长的字符串?

tr是一个很棒的工具,可以用来翻译set of characters成另一个set of characters.

诸如此类的命令sed , awk, perl可用于翻译set of characters成另一个一组字符串,例如,它可以翻译<> 进入 &lt;&gt;,但似乎没有必要为此目的使用这些命令!

还有其他命令可以完成此任务吗?

答案1

我不知道你使用的是哪个 shell,但很可能tr不是内置的。在 bash 或 zsh 中肯定不适合我:) 尝试运行type tr自己看看。

很可能sed是适合这项工作的工具。这就是它的用途。酌情perlawk也。

如果您的情况非常简单,并且您正在使用字符串变量而不是管道,那么您可能会使用真正的内置函数,例如使用 bash 的字符串搜索和替换变量。

string="Stuf with <tag> in it."
escaped=${string//</&lt;}
escaped=${escaped//>/&gt;}
echo $escaped

答案2

如果您想使用标准参数处理,则用另一组多个字符串替换多个字符串会变得很混乱。通常,命令采用一组原子参数,然后是一组原子参数,除了参数在参数之后(--如果不明确,则用 分隔)之外,顺序并不重要。在这种情况下,你将如何构建概要?

这是一个简单的函数,可以完成简单的替换:

$ trs() {
    local string=$1
    shift
    for replacement in "$@"
    do
        string="$(sed -e "s/$replacement/g" <<< "$string")"
    done
    printf "$string"
}
$ trs '1 2 3' '1/foo' '2 3/bar baz'
foo bar baz

或者,您可以使用参数对:

$ trs() {
    local string=$1
    shift
    while [ $# -gt 0 ]
    do
        string="$(sed -e "s/$1/$2/g" <<< "$string")"
        shift 2
    done
    printf "$string"
}
$ trs '1 2 3' 1 foo '2 3' 'bar baz'
foo bar baz

答案3

sed可能很可怕,但是简单的字符到字符串替换sed并不是真的太糟糕。

要替换x为字符串bar,请执行以下操作:

{something-that-outputs-something-on-stdout} | sed -e 's/x/bar/g'

如果这是您要处理的文件,您可以使用:

sed -e 's/x/bar/g' {filename}

(末尾的“g”表示“全局”,这意味着替换该行中的所有出现项,而不仅仅是第一个)

答案4

如果您知道较长的字符串是什么,那么sed -e s/xx/yy/g答案就是可靠的。

但是,如果您希望更通用并接受任何字符串作为输入,例如来自函数参数的字符串,则不能使用 sed:您必须在正则表达式中使用字符串之前对字符串进行转义,这非常困难。

为了更可靠地做到这一点,您可以使用这个 oneliner:

python -c '(lambda s: s.stdout.write(s.stdin.read().replace(*s.argv[1:])))(__import__("sys"))'

将其添加为 .bashrc 中的别名以方便使用:

alias trs='python -c '\''(lambda s: s.stdout.write(s.stdin.read().replace(*s.argv[1:])))(__import__("sys"))'\'''

和:

$ echo /some-path/file | trs -path /dir1/dir2
/some/dir1/dir2/file

背景:我用它作为另一个别名;cds,模拟 zsh 的“cd foo bar”行为,替换foobar的 pwd 中的:

$ function cds { cd "$(pwd | trs "$1" "$2")" ; }

$ mkdir -p /tmp/foo /tmp/bar
$ cd /tmp/foo
$ cds foo bar
$ pwd
/tmp/bar

sed如果我传递了/, 或其他非正则表达式安全字符,则这不适用于某个版本。

相关内容