在 shell 脚本中使用不带空格的 "cut" 作为分隔符



我正在尝试编写一个脚本来读取下面的文件内容并提取每行第 6 列中的值,然后打印没有第 6 列的每一行。逗号用作分隔符。

输入:

123,456,789,101,145,5671,hello world,goodbye for now
223,456,789,101,145,5672,hello world,goodbye for now
323,456,789,101,145,5673,hello world,goodbye for now

我所做的是

#!/bin/bash
for i in `cat test_input.txt`
do
    COLUMN=`echo $i | cut -f6 -d','`
    echo $i | cut -f1-5,7- -d',' >> test_$COLUMN.txt
done

我得到的输出是

test_5671.txt:

123,456,789,101,145,hello

test_5672.txt:

223,456,789,101,145,hello

test_5673.txt:

323,456,789,101,145,hello
"

世界,暂时再见"的其余部分没有写入输出文件,因为似乎"hello"和"world"之间的空格被用作分隔符?

如何获得正确的输出

123,456,789,101,145,hello world,goodbye for now

这不是cut命令的问题,而是你正在使用的for循环的问题。对于第一次循环运行,变量 i 将只包含 123,456,789,101,145,5671,hello .

如果你坚持逐行读取输入文件(效率不是很高),你最好使用这样的读取循环:

while read i
 do
  ...
 done < test_input.txt
echo '123,456,789,101,145,5671,hello world,goodbye for now' | while IFS=, read -r one two three four five six seven eight rest
do
    echo "$six"
    echo "$one,$two,$three,$four,$five,$seven,$eight${rest:+,$rest}"
done

指纹:

5671
123,456,789,101,145,hello world,goodbye for now

有关:+语法,请参阅man bash Parameter Expansion部分(如果已定义$rest为非空,则实质上它会输出逗号和$rest)。

此外,不应使用 for 循环访问文件内容。

正如 ktf 所提到的,您的问题不在于cut,而在于您将行传递到cut的方式。他/她提供的解决方案应该有效。

或者,您可以使用一行awk实现相同的行为:

awk -F, '{for(i=1;i<=NF;i++) {if(i!=6) printf "%s%s",$i,(i==NF)?"n":"," > "test_"$6".txt"}}' test_input.txt

为清楚起见,这里有一个详细的版本:

awk -F, '  # "-F,": using comma as field separator
{ # for each line in file
  for(i=1;i<=NF;i++) {  # for each column
    sep = (i == NF) ? "n" : ","  # column separator
    outfile = "test_"$6".txt"     # output file
    if (i != 6) {  # skip sixth column
      printf "%s%s", $i, sep > outfile
    }
  }
}' test_input.txt

一个简单的方法ID,可以使用tr commende将espace carracter转换为#,并在执行cat命令后将其重新翻译到espace中。

最新更新