对多个文本文件应用相同的 sed 命令

对多个文本文件应用相同的 sed 命令

我正在对文件进行一些预处理。我有 2 个文本文件,其中包含以下格式的数据。

文本文件1

"Name","Age","Class"
"Total Students:","247"
"John","14","8"
"Sara","13","8"

文本文件2

"Name","Age","Class"
"Total Students:","119"
"John","15","9"
"Sara","16","9"

我想做的是从这些文件和引号中删除前 2 行,然后使用以下命令将文件移动到输出目录。

sed '1d' "$file" >> temp.txt
sed -i '1d' temp.txt
sed -i 's/"//g' temp.txt

mv temp.txt output/$file

我面临的问题是,这些命令仅适用于单个文件。文件名是类_8.txt类_9.txt。有什么解决方案可以对两个文件应用相同的命令吗?我想保留原始文件并将处理后的文件移动到输出文件夹。

答案1

您无法方便地sed在多个文件上运行并使其一次性写入多个文件(如果输入和输出需要是单独的文件)。可以使用非标准扩展名或通过在表达式中硬编码输出文件的名称sed

尽管您的操作非常简单,但我们可能想在循环中使用tailand :tr

for file in Class_{8,9}.txt; do
    tail -n +3 "$file" | tr -d '"' >output/"$file"
done

或者,如果你真的想使用sed

for file in Class_{8,9}.txt; do
    sed -e '1,2d' -e 's/"//g' "$file" >output/"$file"
done

您还可以先复制文件,然后sed在副本上一次性运行就地编辑。从某种意义上说,这将循环委托给了 GNU 的内部运作sed

cp Class_{8,9}.txt output
sed -i -e '1,2d' -e 's/"//g' output/Class_{8,9}.txt

请注意,如果任何字段包含嵌入的逗号或换行符,删除双引号将意味着写入无效的 CSV 输出。要仅删除不需要的双引号,请使用 CSV 解析器,例如csvformatfromcsvkit

上述命令都假设这output是一个允许您在其中创建文件的现有目录。

答案2

要从同一命令写入不同的文件sed,您可以使用该w命令或w该命令的标志s

在您的情况下,行的最后一个字段似乎是确定应写入哪个文件的类字段,因此我们根本不需要关心哪个是源文件。我们甚至不需要关心前两行,因为它们可以被忽略,因为它们没有有效的类:

sed -ne 's/"//g;/,8$/woutput/Class_8.txt' -e '/,9$/woutput/Class_9.txt' file*

因此,对于所有行,您删除 的双引号s/"//g,然后/,8$/选择8最后一个字段中的所有行,这些行应该w写入output/Class_8.txt。等级 9 相同。默认输出被该选项抑制-n

当然,这对于大量文件来说是无法扩展的。

答案3

-i.sufinsed添加.suf到旧文件并将更改写入新文件。因此,您可以 1) 用于sed修改文件并保留旧文件的后缀,2) 移动新文件,3) 通过删除后缀将旧文件重命名为原始名称:

sed -i.bup '1,2d;s/"//g' file1.txt file2.txt file3.txt
mv file{1..3}.txt output
rename 's/.bup$//' file{1..3}.txt.bup

rename有时也称为prenameperl-rename取决于发行版)

答案4

假设您想编辑这两个文件并将输出重定向到output具有相同文件名但已编辑版本的目录,那么这awk可能会起作用。

$ awk 'FNR > 1 { gsub(/\"/,""); print > "output/"FILENAME ; next } FNR > 1 { gsub(/\"/,""); print > "output/"FILENAME }' Class_8.txt Class_9.txt

或者作为脚本

$ cat awk.script

FNR > 1 {                      #Remove line 1 from first file
    gsub(/\"/,"")              #Substitute all double quotes for nothing
    print > "output/"FILENAME  #Send the output to new directory with the same filename
    next                       #Move on to the next file
} FNR > 1 {                    #Remove line 1 from second file
    gsub(/\"/,"")              #Substitute all double quotes for nothing
    print > "output/"FILENAME  #Send the output to new directory with the same filename
}

要将脚本与您的文件一起使用,您可以运行以下命令

$ awk -f awk.script Class_8.txt Class_9.txt

输出如下

$ cat output/Class_8.txt
Total Students:,247
John,14,8
Sara,13,8
$ cat output/Class_9.txt
Total Students:,119
John,15,9
Sara,16,9

相关内容