如何避免在 csh 中重复路径变量

发布于 2024-07-06 08:05:00 字数 349 浏览 8 评论 0原文

通常在您的 cshrc 文件中包含类似的内容来设置路径:

set path = ( . $otherpath $path )

但是,当您多次获取 cshrc 文件时,路径会重复,如何防止重复?

编辑:这是一种不干净的做法:

set localpaths = ( . $otherpaths )
echo ${path} | egrep -i "$localpaths" >& /dev/null
if ($status != 0) then
    set path = ( . $otherpaths $path )
endif

It is typical to have something like this in your cshrc file for setting the path:

set path = ( . $otherpath $path )

but, the path gets duplicated when you source your cshrc file multiple times, how do you prevent the duplication?

EDIT: This is one unclean way of doing it:

set localpaths = ( . $otherpaths )
echo ${path} | egrep -i "$localpaths" >& /dev/null
if ($status != 0) then
    set path = ( . $otherpaths $path )
endif

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

物价感观 2024-07-13 08:05:00

我很惊讶没有人使用 tr ":" "\n" | grep -x 技术来搜索给定文件夹是否已存在于 $PATH 中。 有什么理由不这样做?

在 1 行中:

if ! $(echo "$PATH" | tr ":" "\n" | grep -qx "$dir") ; then PATH=$PATH:$dir ; fi

这是我自己编写的一个函数,可以一次将多个文件夹添加到 $PATH(使用“aaa:bbb:ccc”符号作为参数),在添加之前检查每个文件夹是否有重复项:

append_path()
{
    local SAVED_IFS="$IFS"
    local dir
    IFS=:
    for dir in $1 ; do
        if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$dir" ) ; then
            PATH=$PATH:$dir
        fi
    done
    IFS="$SAVED_IFS"
}

可以在如下脚本中调用它this:

append_path "/test:$HOME/bin:/example/my dir/space is not an issue"

它具有以下优点:

  • 没有 bashisms 或任何特定于 shell 的语法。 它与 !#/bin/sh 完美运行(我用破折号进行了测试)
  • 可以一次添加多个文件夹
  • 无需排序,保留文件夹顺序
  • 完美处理文件夹名称中的空格
  • 单个测试无论是否有效$folder 位于开始、结束、中间,或者是 $PATH 中的唯一文件夹(因此避免测试 x:*, *:x, :x:, x,因为这里的许多解决方案都隐式地do)
  • 如果 $PATH 以“:”开头或结尾,或者其中包含“::”(表示当前文件夹),则有效(并保留)
  • 不需要 awksed
  • EPA 友好;) 保留原始 IFS 值,并且所有其他变量都是函数范围的本地变量。

希望有帮助!

Im surprised no one used the tr ":" "\n" | grep -x techique to search if a given folder already exists in $PATH. Any reason not to?

In 1 line:

if ! $(echo "$PATH" | tr ":" "\n" | grep -qx "$dir") ; then PATH=$PATH:$dir ; fi

Here is a function ive made myself to add several folders at once to $PATH (use "aaa:bbb:ccc" notation as argument), checking each one for duplicates before adding:

append_path()
{
    local SAVED_IFS="$IFS"
    local dir
    IFS=:
    for dir in $1 ; do
        if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$dir" ) ; then
            PATH=$PATH:$dir
        fi
    done
    IFS="$SAVED_IFS"
}

It can be called in a script like this:

append_path "/test:$HOME/bin:/example/my dir/space is not an issue"

It has the following advantages:

  • No bashisms or any shell-specific syntax. It run perfectly with !#/bin/sh (ive tested with dash)
  • Multiple folders can be added at once
  • No sorting, preserves folder order
  • Deals perfectly with spaces in folder names
  • A single test works no matter if $folder is at begginning, end, middle, or is the only folder in $PATH (thus avoiding testing x:*, *:x, :x:, x, as many of the solutions here implicitly do)
  • Works (and preserve) if $PATH begins or ends with ":", or has "::" in it (meaning current folder)
  • No awk or sed needed.
  • EPA friendly ;) Original IFS value is preserved, and all other variables are local to the function scope.

Hope that helps!

迷路的信 2024-07-13 08:05:00

好吧,不是在 csh 中,但这就是我在 bash 中将 $HOME/bin 附加到我的路径中的方式...

case $PATH in
    *:$HOME/bin | *:$HOME/bin:* ) ;;
    *) export PATH=$PATH:$HOME/bin
esac

季节品尝...

ok, not in csh, but this is how I append $HOME/bin to my path in bash...

case $PATH in
    *:$HOME/bin | *:$HOME/bin:* ) ;;
    *) export PATH=$PATH:$HOME/bin
esac

season to taste...

清眉祭 2024-07-13 08:05:00

您可以使用以下 Perl 脚本来删除重复项的路径。


#!/usr/bin/perl
#
# ^^ ensure this is pointing to the correct location.
#
# Title:    SLimPath
# Author:   David "Shoe Lace" Pyke <[email protected] >
#   :   Tim Nelson 
# Purpose: To create a slim version of my envirnoment path so as to eliminate
#       duplicate entries and ensure that the "." path was last.
# Date Created: April 1st 1999
# Revision History:
#   01/04/99: initial tests.. didn't wok verywell at all
#       : retreived path throught '$ENV' call
#   07/04/99: After an email from Tim Nelson <[email protected]> got it to
#         work.
#       : used 'push' to add to array
#       : used 'join' to create a delimited string from a list/array.
#   16/02/00: fixed cmd-line options to look/work better
#   25/02/00: made verbosity level-oriented
#
#

use Getopt::Std;

sub printlevel;

$initial_str = "";
$debug_mode = "";
$delim_chr = ":";
$opt_v = 1;

getopts("v:hd:l:e:s:");

OPTS: {
    $opt_h && do {
print "\n$0 [-v level] [-d level] [-l delim] ( -e varname | -s strname | -h )";
print "\nWhere:";
print "\n   -h  This help";
print "\n   -d  Debug level";
print "\n   -l  Delimiter (between path vars)";
print "\n   -e  Specify environment variable (NB: don't include \$ sign)";
print "\n   -s  String (ie. $0 -s \$PATH:/looser/bin/)";
print "\n   -v  Verbosity (0 = quiet, 1 = normal, 2 = verbose)";
print "\n";
        exit;
    };
    $opt_d && do {
        printlevel 1, "You selected debug level $opt_d\n";
        $debug_mode = $opt_d;
    };
    $opt_l && do {
        printlevel 1, "You are going to delimit the string with \"$opt_l\"\n";
        $delim_chr = $opt_l;
    };
    $opt_e && do {
        if($opt_s) { die "Cannot specify BOTH env var and string\n"; }
        printlevel 1, "Using Environment variable \"$opt_e\"\n";
        $initial_str = $ENV{$opt_e};
    };
    $opt_s && do {
        printlevel 1, "Using String \"$opt_s\"\n";
        $initial_str = $opt_s;
    };
}

if( ($#ARGV != 1) and !$opt_e and !$opt_s){
    die "Nothing to work with -- try $0 -h\n";
}

$what = shift @ARGV;
# Split path using the delimiter
@dirs = split(/$delim_chr/, $initial_str);

$dest;
@newpath = ();
LOOP: foreach (@dirs){
    # Ensure the directory exists and is a directory
    if(! -e ) { printlevel 1, "$_ does not exist\n"; next; }
    # If the directory is ., set $dot and go around again
    if($_ eq '.') { $dot = 1; next; }

#   if ($_ ne `realpath $_`){
#           printlevel 2, "$_ becomes ".`realpath $_`."\n";
#   }
    undef $dest;
    #$_=Stdlib::realpath($_,$dest);
    # Check for duplicates and dot path
    foreach $adir (@newpath) { if($_ eq $adir) { 
        printlevel 2, "Duplicate: $_\n";
        next LOOP; 
    }}

    push @newpath, $_;
}

# Join creates a string from a list/array delimited by the first expression
print join($delim_chr, @newpath) . ($dot ? $delim_chr.".\n" : "\n");

printlevel 1, "Thank you for using $0\n";
exit;

sub printlevel {
    my($level, $string) = @_;

    if($opt_v >= $level) {
        print STDERR $string;
    }
}

我希望那有用。

you can use the following Perl script to prune paths of duplicates.


#!/usr/bin/perl
#
# ^^ ensure this is pointing to the correct location.
#
# Title:    SLimPath
# Author:   David "Shoe Lace" Pyke <[email protected] >
#   :   Tim Nelson 
# Purpose: To create a slim version of my envirnoment path so as to eliminate
#       duplicate entries and ensure that the "." path was last.
# Date Created: April 1st 1999
# Revision History:
#   01/04/99: initial tests.. didn't wok verywell at all
#       : retreived path throught '$ENV' call
#   07/04/99: After an email from Tim Nelson <[email protected]> got it to
#         work.
#       : used 'push' to add to array
#       : used 'join' to create a delimited string from a list/array.
#   16/02/00: fixed cmd-line options to look/work better
#   25/02/00: made verbosity level-oriented
#
#

use Getopt::Std;

sub printlevel;

$initial_str = "";
$debug_mode = "";
$delim_chr = ":";
$opt_v = 1;

getopts("v:hd:l:e:s:");

OPTS: {
    $opt_h && do {
print "\n$0 [-v level] [-d level] [-l delim] ( -e varname | -s strname | -h )";
print "\nWhere:";
print "\n   -h  This help";
print "\n   -d  Debug level";
print "\n   -l  Delimiter (between path vars)";
print "\n   -e  Specify environment variable (NB: don't include \$ sign)";
print "\n   -s  String (ie. $0 -s \$PATH:/looser/bin/)";
print "\n   -v  Verbosity (0 = quiet, 1 = normal, 2 = verbose)";
print "\n";
        exit;
    };
    $opt_d && do {
        printlevel 1, "You selected debug level $opt_d\n";
        $debug_mode = $opt_d;
    };
    $opt_l && do {
        printlevel 1, "You are going to delimit the string with \"$opt_l\"\n";
        $delim_chr = $opt_l;
    };
    $opt_e && do {
        if($opt_s) { die "Cannot specify BOTH env var and string\n"; }
        printlevel 1, "Using Environment variable \"$opt_e\"\n";
        $initial_str = $ENV{$opt_e};
    };
    $opt_s && do {
        printlevel 1, "Using String \"$opt_s\"\n";
        $initial_str = $opt_s;
    };
}

if( ($#ARGV != 1) and !$opt_e and !$opt_s){
    die "Nothing to work with -- try $0 -h\n";
}

$what = shift @ARGV;
# Split path using the delimiter
@dirs = split(/$delim_chr/, $initial_str);

$dest;
@newpath = ();
LOOP: foreach (@dirs){
    # Ensure the directory exists and is a directory
    if(! -e ) { printlevel 1, "$_ does not exist\n"; next; }
    # If the directory is ., set $dot and go around again
    if($_ eq '.') { $dot = 1; next; }

#   if ($_ ne `realpath $_`){
#           printlevel 2, "$_ becomes ".`realpath $_`."\n";
#   }
    undef $dest;
    #$_=Stdlib::realpath($_,$dest);
    # Check for duplicates and dot path
    foreach $adir (@newpath) { if($_ eq $adir) { 
        printlevel 2, "Duplicate: $_\n";
        next LOOP; 
    }}

    push @newpath, $_;
}

# Join creates a string from a list/array delimited by the first expression
print join($delim_chr, @newpath) . ($dot ? $delim_chr.".\n" : "\n");

printlevel 1, "Thank you for using $0\n";
exit;

sub printlevel {
    my($level, $string) = @_;

    if($opt_v >= $level) {
        print STDERR $string;
    }
}

i hope thats useful.

千寻… 2024-07-13 08:05:00

十年来我一直在使用以下 (Bourne/Korn/POSIX/Bash) 脚本:

:   "@(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp $"
#
#   Print minimal version of $PATH, possibly removing some items

case $# in
0)  chop=""; path=${PATH:?};;
1)  chop=""; path=$1;;
2)  chop=$2; path=$1;;
*)  echo "Usage: `basename $0 .sh` [$PATH [remove:list]]" >&2
    exit 1;;
esac

# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN   {   # Sort out which path components to omit
            chop="'"$chop"'";
            if (chop != "") nr = split(chop, remove); else nr = 0;
            for (i = 1; i <= nr; i++)
                omit[remove[i]] = 1;
        }
{
    for (i = 1; i <= NF; i++)
    {
        x=$i;
        if (x == "") x = ".";
        if (omit[x] == 0 && path[x]++ == 0)
        {
            output = output pad x;
            pad = ":";
        }
    }
    print output;
}'

在 Korn shell 中,我使用:

export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/extra/bin)

这使我的 PATH 包含前面的新目录和其他 bin 目录,以及一份主路径值中的每个目录名称,除了旧的和额外的 bin 目录已删除 bin 之外。

您必须将其改编为 C shell(抱歉 - 但我非常相信 C Shell 编程被认为是有害的)。 首先,您不必摆弄冒号分隔符,因此生活实际上更容易。

I've been using the following (Bourne/Korn/POSIX/Bash) script for most of a decade:

:   "@(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp $"
#
#   Print minimal version of $PATH, possibly removing some items

case $# in
0)  chop=""; path=${PATH:?};;
1)  chop=""; path=$1;;
2)  chop=$2; path=$1;;
*)  echo "Usage: `basename $0 .sh` [$PATH [remove:list]]" >&2
    exit 1;;
esac

# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN   {   # Sort out which path components to omit
            chop="'"$chop"'";
            if (chop != "") nr = split(chop, remove); else nr = 0;
            for (i = 1; i <= nr; i++)
                omit[remove[i]] = 1;
        }
{
    for (i = 1; i <= NF; i++)
    {
        x=$i;
        if (x == "") x = ".";
        if (omit[x] == 0 && path[x]++ == 0)
        {
            output = output pad x;
            pad = ":";
        }
    }
    print output;
}'

In Korn shell, I use:

export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/extra/bin)

This leaves me with PATH containing the new and other bin directories at the front, plus one copy of each directory name in the main path value, except that the old and extra bin directories have bin removed.

You would have to adapt this to C shell (sorry - but I'm a great believer in the truths enunciated at C Shell Programming Considered Harmful). Primarily, you won't have to fiddle with the colon separator, so life is actually easier.

终弃我 2024-07-13 08:05:00

好吧,如果您不关心路径的顺序,您可以执行以下操作:

set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)

这将对您的路径进行排序并删除任何相同的额外路径。 如果你有 。 在您的路径中,您可能需要使用 grep -v 删除它并在末尾重新添加它。

Well, if you don't care what order your paths are in, you could do something like:

set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)

That will sort your paths and remove any extra paths that are the same. If you have . in your path, you may want to remove it with a grep -v and re-add it at the end.

软甜啾 2024-07-13 08:05:00

这是一篇没有排序的长单行:
set path = ( echo $path | tr ' ' '\n' | perl -e 'while (<>) { print $_ except $s{$_}++; }' | tr '\ n''')

Here is a long one-liner without sorting:
set path = ( echo $path | tr ' ' '\n' | perl -e 'while (<>) { print $_ unless $s{$_}++; }' | tr '\n' ' ')

烟花易冷人易散 2024-07-13 08:05:00

dr_peper,

我通常更喜欢坚持使用我所使用的 shell 的脚本功能。使其更加便携。 所以,我喜欢你使用 csh 脚本的解决方案。 我只是将其扩展为在 localdirs 中的每个目录上工作,以使其适合我自己。

foreach dir ( $localdirs )
    echo ${path} | egrep -i "$dir" >& /dev/null
    if ($status != 0) then
        set path = ( $dir $path )
    endif
end

dr_peper,

I usually prefer to stick to scripting capabilities of the shell I am living in. Makes it more portable. So, I liked your solution using csh scripting. I just extended it to work on per dir in the localdirs to make it work for myself.

foreach dir ( $localdirs )
    echo ${path} | egrep -i "$dir" >& /dev/null
    if ($status != 0) then
        set path = ( $dir $path )
    endif
end
别再吹冷风 2024-07-13 08:05:00

使用 sed(1) 删除重复项。

$ PATH=$(echo $PATH | sed -e 's/$/:/;s/^/:/;s/:/::/g;:a;s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g;ta;s/::*/:/g;s/^://;s/:$//;')

这将在第一个实例之后删除重复项,这可能是也可能不是您想要的,例如:

$ NEWPATH=/bin:/usr/bin:/bin:/usr/local/bin:/usr/local/bin:/bin
$ echo $NEWPATH | sed -e 's/$/:/; s/^/:/; s/:/::/g; :a; s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g; t a; s/::*/:/g; s/^://; s/:$//;'
/bin:/usr/bin:/usr/local/bin
$

享受!

Using sed(1) to remove duplicates.

$ PATH=$(echo $PATH | sed -e 's/$/:/;s/^/:/;s/:/::/g;:a;s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g;ta;s/::*/:/g;s/^://;s/:$//;')

This will remove the duplicates after the first instance, which may or may not be what you want, e.g.:

$ NEWPATH=/bin:/usr/bin:/bin:/usr/local/bin:/usr/local/bin:/bin
$ echo $NEWPATH | sed -e 's/$/:/; s/^/:/; s/:/::/g; :a; s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g; t a; s/::*/:/g; s/^://; s/:$//;'
/bin:/usr/bin:/usr/local/bin
$

Enjoy!

北风几吹夏 2024-07-13 08:05:00

这是我使用的 - 也许其他人会发现它有用:

#!/bin/csh
#  ABSTRACT
#    /bin/csh function-like aliases for manipulating environment
#    variables containing paths.
#
#  BUGS
#    - These *MUST* be single line aliases to avoid parsing problems apparently related
#      to if-then-else
#    - Aliases currently perform tests in inefficient in order to avoid parsing problems
#    - Extremely fragile - use bash instead!!
#
#  AUTHOR
#    J. P. Abelanet - 11/11/10

#  Function-like alias to add a path to the front of an environment variable
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: prepend_path ENVVARIABLE /path/to/prepend
alias prepend_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$arg2":"$\!:1";'

#  Function-like alias to add a path to the back of any environment variable 
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: append_path ENVVARIABLE /path/to/append
alias append_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$\!:1":"$arg2";'

Here's what I use - perhaps someone else will find it useful:

#!/bin/csh
#  ABSTRACT
#    /bin/csh function-like aliases for manipulating environment
#    variables containing paths.
#
#  BUGS
#    - These *MUST* be single line aliases to avoid parsing problems apparently related
#      to if-then-else
#    - Aliases currently perform tests in inefficient in order to avoid parsing problems
#    - Extremely fragile - use bash instead!!
#
#  AUTHOR
#    J. P. Abelanet - 11/11/10

#  Function-like alias to add a path to the front of an environment variable
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: prepend_path ENVVARIABLE /path/to/prepend
alias prepend_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$arg2":"$\!:1";'

#  Function-like alias to add a path to the back of any environment variable 
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: append_path ENVVARIABLE /path/to/append
alias append_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$\!:1":"$arg2";'
倒带 2024-07-13 08:05:00

在 csh 中设置路径(小写,csh 变量)而不是 PATH(环境变量)时,可以使用 set -f 和 set -l,这只会保留每个列表元素的一次出现(首选保留第一个或分别是最后)。

https://nature.berkeley.edu/~casterln/tcsh/Builtin_commands。 html#set

所以像这样

cat foo.csh # 或 .tcshrc 或其他什么:
set -f path = (/bin /usr/bin . ) # 初始值
set -f path = ($path /mycode /hercode /usr/bin ) # 添加新内容和重复内容

每次 source 时,不会继续使用重复项扩展 PATH:

% source foo.csh
% 回显 $PATH
% /bin:/usr/bin:.:/mycode:/hercode
% 源文件 foo.csh
% 回显 $PATH
% /bin:/usr/bin:.:/mycode:/hercode

set -f there 确保仅保留每个 PATH 元素的第一次出现。

When setting path (lowercase, the csh variable) rather than PATH (the environment variable) in csh, you can use set -f and set -l, which will only keep one occurrence of each list element (preferring to keep either the first or last, respectively).

https://nature.berkeley.edu/~casterln/tcsh/Builtin_commands.html#set

So something like this

cat foo.csh # or .tcshrc or whatever:
set -f path = (/bin /usr/bin . ) # initial value
set -f path = ($path /mycode /hercode /usr/bin ) # add things, both new and duplicates

Will not keep extending PATH with duplicates every time you source it:

% source foo.csh
% echo $PATH
% /bin:/usr/bin:.:/mycode:/hercode
% source foo.csh
% echo $PATH
% /bin:/usr/bin:.:/mycode:/hercode

set -f there ensures that only the first occurrence of each PATH element is kept.

满天都是小星星 2024-07-13 08:05:00

我总是在 .cshrc 中从头开始设置路径。
也就是说,我从一条基本路径开始,例如:(

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)

取决于系统)。

然后做:

set path = ($otherPath $path)

添加更多东西

I always set my path from scratch in .cshrc.
That is I start off with a basic path, something like:

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)

(depending on the system).

And then do:

set path = ($otherPath $path)

to add more stuff

儭儭莪哋寶赑 2024-07-13 08:05:00

我和原来的问题有同样的需求。
基于您之前的答案,我在 Korn/POSIX/Bash 中使用过:

export PATH=$(perl -e 'print join ":", grep {!$h{$_}++} split ":", "'$otherpath:$PATH\")

我很难直接在 csh 中翻译它(csh 转义规则是疯狂的)。 我已经使用过(按照 dr_pepper 的建议):

set path = ( `echo $otherpath $path | tr ' ' '\n' | perl -ne 'print $_ unless $h{$_}++' | tr '\n' ' '`)

您有想法进一步简化它(减少管道数量)吗?

I have the same need as the original question.
Building on your previous answers, I have used in Korn/POSIX/Bash:

export PATH=$(perl -e 'print join ":", grep {!$h{$_}++} split ":", "'$otherpath:$PATH\")

I had difficulties to translate it directly in csh (csh escape rules are insane). I have used (as suggested by dr_pepper):

set path = ( `echo $otherpath $path | tr ' ' '\n' | perl -ne 'print $_ unless $h{$_}++' | tr '\n' ' '`)

Do you have ideas to simplify it more (reduce the number of pipes) ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文