Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell “简洁轻便”;加入;在Unix命令行上_Shell_Unix - Fatal编程技术网

Shell “简洁轻便”;加入;在Unix命令行上

Shell “简洁轻便”;加入;在Unix命令行上,shell,unix,Shell,Unix,如何将多行合并为一行,在新行字符所在的位置使用分隔符,并避免使用尾随分隔符,或者忽略空行 例如。考虑一个文本文件, fo.txt,用三行: foo bar baz 所需输出为: foo,bar,baz 我现在使用的命令: tr '\n' ',' <foo.txt |sed 's/,$//g' 什么是: 最便携、简洁、可读的方式 使用非标准unix工具的最简洁方法 当然,我可以写点东西,或者只用一个别名。但是我很想知道这些选项。也许有点奇怪,粘贴是一种很好的方法: paste -s -

如何将多行合并为一行,在新行字符所在的位置使用分隔符,并避免使用尾随分隔符,或者忽略空行

例如。考虑一个文本文件,<代码> fo.txt,用三行:

foo
bar
baz
所需输出为:

foo,bar,baz
我现在使用的命令:

tr '\n' ',' <foo.txt |sed 's/,$//g'
什么是:

  • 最便携、简洁、可读的方式
  • 使用非标准unix工具的最简洁方法

  • 当然,我可以写点东西,或者只用一个别名。但是我很想知道这些选项。

    也许有点奇怪,
    粘贴是一种很好的方法:

    paste -s -d","
    
    这不会处理你提到的空行。为此,请通过
    grep
    ,首先:

    grep -v '^$' | paste -s -d"," -
    

    只是为了好玩,这里有一个全内置的解决方案

    IFS=$'\n' read -r -d '' -a data < foo.txt ; ( IFS=, ; echo "${data[*]}" ; )
    
    IFS=$'\n'read-r-d'-a data
    如果尾随换行符有问题,可以使用
    printf
    而不是
    echo


    这是通过设置
    IFS
    read
    将拆分的分隔符,仅为换行符而不是其他空格,然后告诉
    read
    在到达
    nul
    之前不要停止读取,而不是它通常使用的换行符,并将读取的每个项添加到数组(
    -a
    )数据中。然后,在子shell中,为了不碰撞交互式shell的
    IFS
    ,我们将
    IFS
    设置为
    ,并用
    *
    扩展数组,该数组用
    IFS
    中的第一个字符分隔数组中的每个项。这
    sed
    一行应该有效-

    sed-e:a-e'N;s/\n/,/;ba'文件

    测试:

    [jaypal:~/Temp] cat file
    foo
    bar
    baz
    
    [jaypal:~/Temp] sed -e :a -e 'N;s/\n/,/;ba' file
    foo,bar,baz
    
    要处理空行,可以删除空行并将其输送到上面的一个衬里

    sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba'
    

    我需要完成类似的工作,从文件中打印一个逗号分隔的字段列表,并且很高兴将STDOUT管道化到
    xargs
    ruby
    ,如下所示:

    cat data.txt | cut -f 16 -d ' ' | grep -o "\d\+" | xargs ruby -e "puts ARGV.join(', ')"
    
    Perl:

    或者更短更快,令人惊讶的是:

    cat data.txt | perl -pe 'if(!eof){s/\n/,/}'
    
    或者,如果您愿意:

    cat data.txt | perl -pe 's/\n/,/ unless eof'
    

    使用
    ex
    (也忽略空行)将行与空格连接起来的简单方法,使用:

    如果要将结果打印到标准输出,请尝试:

    ex +%j +%p -scq! foo.txt
    
    要连接没有空格的行,请使用
    +%j而不是
    +%j

    要使用不同的分隔符,有点棘手:

    ex +"g/^$/d" +"%s/\n/_/e" +%p -scq! foo.txt
    
    其中,
    g/^$/d
    (或
    v/\S/d
    )删除空行,
    S/\n/\u/
    是替换,其工作原理基本上与使用
    sed
    相同,但适用于所有行(
    %
    )。解析完成后,打印缓冲区(
    %p
    )。最后是
    -cq执行vi
    q
    命令,基本上不保存就退出(
    -s
    用于使输出静音)

    请注意,
    ex
    相当于
    vi-e


    此方法非常便于移植,因为大多数Linux/Unix在默认情况下都附带了
    ex
    /
    vi
    。而且它比使用
    sed
    更兼容,其中就地参数(
    -i
    )不是标准扩展,并且实用程序本身更面向流,因此它不是那么可移植。

    如何使用xargs

    为了你的案子

    $ cat foo.txt | sed 's/$/, /' | xargs
    

    请注意xargs命令输入的限制长度。(这意味着很长的输入文件不能用它来处理。)

    我有一个日志文件,其中一些数据被分成多行。发生这种情况时,第一行的最后一个字符是分号(;)。我使用以下命令连接这些线:

    for LINE in 'cat $FILE | tr -s " " "|"'
    do
        if [ $(echo $LINE | egrep ";$") ]
        then
            echo "$LINE\c" | tr -s "|" " " >> $MYFILE
        else
            echo "$LINE" | tr -s "|" " " >> $MYFILE
        fi
    done
    
    结果是一个文件,其中日志文件中拆分的行在我的新文件中是一行。

    我的答案是:

    awk '{printf "%s", ","$0}' foo.txt
    

    printf
    就足够了。我们不需要
    -F“\n”
    来更改字段分隔符。

    @codaddict和我都不需要,但我必须承认,我一点也不觉得直观-我总是需要查看手册页来了解这一点。我当然很想看看其他人的建议。还有其他方法,但没有更好的(有趣的方法有点害羞)。它似乎没有忽略空行,但这仍然非常好,适用于我的用例。谢谢为了增强可移植性,考虑在<代码>粘贴> <代码>命令的末尾添加<代码> -/COD>每当期望从 STDIN < /代码>读取时。(某些版本的
    粘贴
    ,如BSD,除非明确地将
    -
    传递给它,否则不会从
    标准输入中读取。)感谢您提供有关
    粘贴
    的提示!我注意到它只允许单字符分隔符,默认情况下是
    \t
    。要完成更长的分隔符(例如
    ):
    cat foo.txt | paste-s | sed's/\t/,/g'
    有趣,但是可移植性并不好,因为纯
    sh
    shell
    read
    命令中没有
    -d
    选项。@mykhal:True。然而,
    bash
    可以在许多系统上找到,因此它有一些实用性。如果您想要便携性,那么阵列可能也已经过时了,否则您可以简单地使用
    while
    循环来解决
    -d
    的不足。对于一个合适的、可移植的所有内置版本,您需要像
    c=;而IFS=read-rd;如果有,就去做![-z“$d”];然后printf“$c$d”;fic=;完成
    ,但对于知道
    -r
    读取
    仍然失败,但可以忽略,并假设内置
    printf
    ,因此如果效率很重要,
    echo
    可能会更好。不过,公认的答案要好得多!可能的重复会在输出的开头添加一个虚假的逗号-1表示不进行测试。它的好处是可以使用任何字符串,而不仅仅是一个简单的逗号。公认的答案不那么通用。我特别喜欢最后一次迭代,尽管我会这样写:
    perl-pe的/\n/,/除非eof'data.txt
    (不需要
    $ cat foo.txt | sed 's/$/, /' | xargs
    
    for LINE in 'cat $FILE | tr -s " " "|"'
    do
        if [ $(echo $LINE | egrep ";$") ]
        then
            echo "$LINE\c" | tr -s "|" " " >> $MYFILE
        else
            echo "$LINE" | tr -s "|" " " >> $MYFILE
        fi
    done
    
    awk '{printf "%s", ","$0}' foo.txt