替换字符,除非它前面带有子字符串

时间:2018-10-09 13:38:21

标签: bash sed

我有很多文件,例如

name.of.file.to.change.fastq

我想将名称中的所有句点都改为下划线,除了要获取“ pastq”之前的最后一个句点

name_of_file_to_change.fastq

我已经看到了使用sed替换字符的答案here,除非后面有某个字符,但是我无法弄清楚如何将单个字符的搜索范围扩展为子字符串。

3 个答案:

答案 0 :(得分:1)

使用Perl风味的rename,您可以

rename -n 's/\.fastq$//; tr/./_/; $_.=".fastq"' *.fastq
# or
rename -n 'tr/./_/; s/_(?=fastq$)/./' *.fastq

答案 1 :(得分:1)

sed在这方面是过大的。尝试以下Bash(+ mv)代码:

shopt -s nullglob   # Globs that match nothing expand to nothing
shopt -s dotglob    # Globs can expand to names that start with '.'

for file in *.*.fastq ; do
    base=${file%.fastq}     # Remove '.fastq' suffix
    newbase=${base//./_}    # Change all '.' to '_'
    newfile=$newbase.fastq  # Add back the '.fastq' suffix

    # If the new filename already exists, issue a warning and don't clobber it
    if [[ -e $newfile || -L $newfile ]] ; then
        printf 'Warning: "%s" exists.  Skipping "%s"\n' "$newfile" "$file" >&2
    else
        mv -- "$file" "$newfile"
    fi
done

有关${file%.fastq}${base//./_}的说明,请参见Parameter expansion [Bash Hackers Wiki]

答案 2 :(得分:1)

先尝试执行echo,然后再执行mv:

echo mv ${f} $(tr '.' '_' <<< "${f%.*}").${f##*.}
# When ok
mv ${f} $(tr '.' '_' <<< "${f%.*}").${f##*.}