替换/删除文件中列之间的多余空格

时间:2017-01-14 03:25:46

标签: bash awk sed cut

我正在尝试解析具有类似内容的文件:

I am a string         12831928  
I am another string           41327318   
A set of strings      39842938  
Another string           3242342  

我希望out文件以制表符分隔:

I am a string\t12831928  
I am another string\t41327318   
A set of strings\t39842938  
Another string\t3242342 

我尝试了以下内容:

sed 's/\s+/\t/g' filename > outfile

我也尝试了cut和awk。

6 个答案:

答案 0 :(得分:2)

只需使用awk:

$ awk -F'  +' -v OFS='\t' '{sub(/ +$/,""); $1=$1}1' file
I am a string   12831928
I am another string     41327318
A set of strings        39842938
Another string  3242342

故障:

-F'  +'           # tell awk that input fields (FS) are separated by 2 or more blanks
-v OFS='\t'       # tell awk that output fields are separated by tabs
'{sub(/ +$/,"");  # remove all trailing blank spaces from the current record (line)
$1=$1}            # recompile the current record (line) replacing FSs by OFSs
1'                # idiomatic: any true condition invokes the default action of "print"

我强烈推荐Arnold Robbins撰写的Effective Awk Programming,第4版。

答案 1 :(得分:0)

sed -E 's/[ ][ ]+/\\t/g' filename > outfile

注意:[ ]openBracket Space closeBracket

-E用于扩展正则表达式支持。

双括号[ ][ ]+仅替换标签超过1个连续空格。

在sed。的MacOS和Ubuntu版本上测试。

答案 2 :(得分:0)

困难在于每行不同数量的单词。虽然您可以使用awk处理此问题,但是将一行中的每个单词读入数组然后tab - 分隔每行中的最后一个单词的简单脚本也会起作用:

#!/bin/bash

fn="${1:-/dev/stdin}"

while read -r line || test -n "$line"; do
    arr=( $(echo "$line") )
    nword=${#arr[@]}
    for ((i = 0; i < nword - 1; i++)); do
        test "$i" -eq '0' && word="${arr[i]}" || word=" ${arr[i]}"
        printf "%s" "$word"
    done
    printf "\t%s\n" "${arr[i]}"
done < "$fn"

示例使用/输出

(使用输入文件)

$ bash rfmttab.sh < dat/tabfile.txt
I am a string   12831928
I am another string     41327318
A set of strings        39842938
Another string  3242342

每个数字都来自字符串的其余部分tab-delimited。仔细看看,如果您有任何问题,请告诉我。

答案 3 :(得分:0)

您的输入在每行的末尾都有空格,这使得事情比没有输入更困难。此sed命令将使用选项卡替换最后一列之前的空格:

$ sed 's/[[:blank:]]*\([^[:blank:]]*[[:blank:]]*\)$/\t\1/' infile | cat -A
I am a string^I12831928  $
I am another string^I41327318   $
A set of strings^I39842938  $
Another string^I3242342  $

这匹配 - 锚定在行的末尾 - 空白,非空白和空白,每个零或更多。捕获后的最后一列和可选空格。

最后一列之前的空格然后被一个标签替换,其余的保持不变 - 请参阅输出管道cat -A以显示明确的行结尾,^I表示标签字符。

如果每行末尾都有 no 空白,则会简化为

sed 's/[[:blank:]]*\([^[:blank:]]*\)$/\t\1/' infile

请注意,某些seds,特别是在MacOS中找到的BSD sed,在替换中不能使用\t作为标签。在这种情况下,您必须改为使用'$'\t'''"$(printf '\t')"'

答案 4 :(得分:0)

另一种方法,sed rev$ rev file | sed -r 's/ +/\t/1' | rev

*/2 * * * * mkdir /var/www/html/test && cp -rf /var/www/html/emaillist.txt /var/www/html/test

答案 5 :(得分:0)

每行都有尾随空格。所以你可以一次完成两个sed表达式:

$ sed -E -e 's/ +$//' -e $'s/  +/\t/' /tmp/file  
I am a string   12831928
I am another string 41327318
A set of strings    39842938
Another string  3242342

注意$'s/ +/\t/':这告诉bash在调用\t之前用实际制表符替换sed

要显示这些删除和\t插入位于正确的位置,您可以执行以下操作:

$ sed -E -e 's/ +$/X/' -e $'s/  +/Y/' /tmp/file  
I am a stringY12831928X
I am another stringY41327318X
A set of stringsY39842938X
Another stringY3242342X
相关问题