使用 Bash 脚本从多个文件中删除前 n 行和 x 列

Deleting first n rows and column x from multiple files using Bash script

我知道 "deleting n rows" 和 "deleting column x" 问题之前都已单独回答过。我目前的问题是,我正在编写我的第一个 bash 脚本,但无法使该脚本按我希望的方式工作。

file0001.csv(一个文件夹里有几百个这样的文件)

Data number of lines 540
No.,Profile,Unit
1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm

期望的输出

1,1027.84
2,1027.92
3,1028
4,1028.81

我可以单独使用 sed 和 cut,但由于某些原因,以下 bash 脚本没有考虑 cut。它还给我一个错误 "sed: can't read ls: No such file or directory",但 sed 成功并且输出保存到原始文件中。

sem2csv.sh

for files in 'ls *.csv'  #list of all .csv files
do
  sed '1,2d' -i $files | cut -f  '1-2' -d  ','
done

实际输出:

1,1027.84,µm
2,1027.92,µm
3,1028,µm
4,1028.81,µm

我知道可能有 awk 单行代码,但我真的很想了解为什么这个特定的 bash 脚本不是预期的 运行。我错过了什么?

sed-i 选项就地修改文件。您到 cut 的管道没有收到任何输入,因为 sed -i 没有产生任何输出。如果没有此选项,sed 会将结果写入标准输出,而不是返回文件,然后您的管道就会工作;但是你必须自己将结果写回原始文件。

此外,单引号会阻止扩展——您 "looping" 覆盖了单个文字字符串 ls *.csv。您不是 quoting it properly 的事实会导致字符串在 内部 循环中进行通配符扩展。因此,在变量插值之后,您的 sed 命令扩展为

sed -i 1,2d ls *.csv

and then shell 展开 *.csv 因为它没有被引用。 (您应该已经收到警告,指出当前目录中也没有名为 ls 的文件。)您可能试图复制一个使用反引号 (ASCII 96) 而不是单引号 (ASCII 39) 的示例 - - 差别很大。

无论如何,lsuseless -- 正确的习语是

for files in *.csv; do
  sed '1,2d' "$files" ...   # the double quotes here are important
done

混合使用 sedcut 通常不是一个好主意,因为您可以用一个简单的 sed 脚本来表达 cut 可以做的任何事情。所以你的整个脚本可以是

for f in *.csv; do
    sed -i -e '1,2d' -e 's/,[^,]*$//' "$f"
done

表示删除最后一个逗号及其后的所有内容。 (如果您的 sed 不喜欢多个 -e 选项,请尝试使用分号分隔符:sed -i '1,2d;s/,[^,]*$//' "$f"

你可以用awk,

$ awk 'NR>2{sub(/,[^,]*$/,"",[=10=]);print}' file
1,1027.84
2,1027.92
3,1028
4,1028.81

sed -i '1,2d;s/,[^,]*$//' file
  • 1,2d; 用于删除前两行。
  • s/,[^,]*$// 删除剩余行中的最后一个逗号部分。