Shell脚本以批量替换.csv文件中的特定字符串

时间:2019-06-16 18:58:21

标签: shell batch-processing

我想替换原始csv文件中的一些字符串以供进一步使用,并且我搜索了互联网并创建了脚本。但似乎它们不起作用。希望任何人都能帮助我

csv文件就是这样,我想删除“ ^ M”和“#Columns:”,以便我可以读取我的文件。

# Task: bending1^M
# Frequency (Hz): 20^M
# Clock (millisecond): 250^M
# Duration (seconds): 120^M
# Columns: time,avg_rss12,var_rss12,avg_rss13,var_rss13,avg_rss23,var_rss23^M
#!/usr/bin/env bash
function scandir(){
cd `dirname $0`
echo `pwd`
local cur_dir parent_dir workir
workdir=$1
cd ${workdir}

if [ ${workdir}="/" ]
then 
    cur_dir=""
else
    cur_dir=$(pwd)
fi

for dirlist in $(ls ${cur_dir})
do
    if test -d ${dirlist}
    then
        cd ${dirlist}
        scandir ${cur_dir}/${dirlist}
        cd ..
    else
        vi ${cur_dir}/${dirlist} << EOF
        :%s/\r//g
        :%s/\#\ Columns:\ //g
        :wq
        EOF
    fi
done
}

3 个答案:

答案 0 :(得分:1)

您的整个脚本看起来像:

find "$workdir" -type f | xargs -n1 sed -i -e 's/\r//g; s/^# Columns://'

脚本注释:

  • 检查脚本在https://www.shellcheck.net/上的有效性
  • 此处<< EOF的文档无效。结束词EOF 必须从脚本内行的开头开始:

    vi ${cur_dir}/${dirlist} << EOF
    :%s/\r//g
    :%s/\#\ Columns:\ //g
    :wq
EOF
#^^ no spaces in front of EOF, also no spaces/tabs after EOF
# the whole line needs to be exactly 'EOF'

前面不能有空格和制表符。另外,我不认为vi并不是在文件上运行替换的最佳工具,也不知道:前面的制表符或空格如何起作用。您可能想尝试在:前面使用空格字符来运行它:

    vi ${cur_dir}/${dirlist} << EOF
:%s/\r//g
:%s/\#\ Columns:\ //g
:wq
EOF
  • 反引号`为deprecated,可读性较差,并且不允许轻松嵌套。请改用$( ... )命令替换。
  • echo`pwd`只是对echo的无效使用,只需使用pwd
  • for dirlist in $(ls parsing ls output is bad。请改用find命令,如果需要,也可以使用shell球化,即。 for dirlist in *
  • if [ ${workdir}="/" ]无效。这将测试字符串"${workdir}=/是否不为空。 Bash具有空间意识,它需要=和操作数之间有一个空格。应该是if [ "${workdir}" = "/" ]
  • Always quote your variables。不要cd ${dirlist}cd "${dirlist}",依此类推。

答案 1 :(得分:1)

贴出正确的答案是正确的,但我建议使用以下语法:

find "$1" -type f -name '*.csv' -exec sed -e 's/\r$//;s/^# Columns: //' -i~ {} +
  • 在查找命令末尾使用+而不是\;将允许sed一次处理多个文件,从而减少了派生操作并加快了整个工作的速度。

  • ~之后的-i选项将通过在名称末尾附加波浪号而不是删除它们来重命名现有文件。

  • 使用-type f将确保仅处理文件(没有符号链接,目录,套接字,fifos,设备...)

答案 2 :(得分:0)

您可以将整个脚本简化为一个命令,而不必使用Vim处理文件:

find ${workdir} -name '*.csv' -exec sed -i -e 's/\r$//; /^#/d' '{}' \;

说明:

  • find <dir> -name <pattern> -exec <command> \;将在每个文件上搜索<dir> for files matching and execute`。您要搜索CSV文件并对其进行处理(对它们运行命令)。

  • 在找到的每个(CSV)文件上运行的命令将为sed -i -e 's/\r$//; /^#/d'。这意味着就地编辑文件(-i)并对其进行两次转换。 s/\r$//将删除每行中的^M,而/^#/d将删除所有以#开头的行。

  • '{}'替换为find找到的文件,并且\;标志着find运行的命令的结尾(请参阅find手册页)。

您的大多数脚本模仿find命令的一部分。那不是一个好主意。

另外,对于简单的文本处理,使用sed而不是调用诸如Vim之类的编辑器更容易,更快捷。