首页 > 解决方案 > 执行 sed 命令时,文件中的某些选项卡会转换为单个空格

问题描述

背景

我有一个 .xyz 文件,我需要从中删除一组特定的行。以及做一些文本替换。我有一个单独的 .txt 文件,其中包含一个整数列表,对应于需要删除的行号,另一个用于需要替换的行。该文件将被调用atomremove.txt并如下所示。另一个文件的结构类似。

就像一个抢先式 TL;DR:我的输入文件中的选项卡碰巧有一个额外的空格(因为不管有没有一个额外的空格,它们都会对齐到某个位置),最终被转换为输出文件中的单个空格。

14
13
11
10
4

我需要从中删除行的 xyz 文件看起来像这样。

24
Comment block
H   18.38385    15.26701    2.28399
C   19.32295    15.80772    2.28641
O   16.69023    17.37471    2.23138
B   17.99018    17.98940    2.24243
C   22.72612    1.13322     2.17619
C   14.47116    18.37823    2.18809
C   15.85803    18.42398    2.20614
C   20.51484    15.08859    2.30584
C   22.77653    3.65203     2.19000
H   20.41328    14.02079    2.31959
H   22.06640    8.65013     2.27145
C   19.33725    17.20040    2.26894
H   13.96336    17.42048    2.19342
H   21.69450    3.68090     2.22196
C   23.01832    9.16815     2.25575
C   23.48143    2.42830     2.16161
H   22.07113    11.03567    2.32659
C   13.75496    19.59644    2.16380
O   23.01248    6.08053     2.20226
C   12.41476    19.56937    2.14732
C   16.54400    19.61620    2.20021
C   23.50500    4.83405     2.17735
C   23.03249    10.56089    2.28599
O   17.87129    19.42333    2.22107

我的代码

尽管输出不如预期,但我成功地进行了线路移除和替换。它似乎用空格替换了一些选项卡,特别是对于只有 5 个小数的“y”坐​​标的行。我将首先分享结果输出,然后是我的代码。

这是输出

19
Comment Block
H   18.38385    15.26701    2.28399
C   19.32295    15.80772    2.28641
O   16.69023    17.37471    2.23138
H   22.72612    1.13322 2.17619
C   14.47116    18.37823    2.18809
C   15.85803    18.42398    2.20614
C   20.51484    15.08859    2.30584
C   22.77653    3.65203 2.19000
C   19.33725    17.20040    2.26894
C   23.01832    9.16815 2.25575
C   23.48143    2.42830 2.16161
H   22.07113    11.03567    2.32659
C   13.75496    19.59644    2.16380
O   23.01248    6.08053 2.20226
C   12.41476    19.56937    2.14732
C   16.54400    19.61620    2.20021
C   23.50500    4.83405 2.17735
H   23.03249    10.56089    2.28599
O   17.87129    19.42333    2.22107

这是我的代码。

atomstorefile="./extract_internal/atomremove.txt"
atomchangefile="./extract_internal/atomchange.txt"

temp="temp.txt"
tempp="tempp.txt"
temppp="temppp.txt"
filestoreloc="./"$basefilename"_xyzoutputs/chops"

#get number of files in directory and set a loop for that # of files
numfiles=$( ls "./"$basefilename"_xyzoutputs/splits" | wc -l )
numfiles=$(( numfiles/2 ))
counter=1

while [ $counter -lt $(( numfiles + 1 )) ];
do
    #set a loop for each split half
    splithalf=1
    while [ $splithalf -lt 3 ];
    do
        #storing the xyz file in a temp file for edits (non destructive)
        cat ./"$basefilename"_xyzoutputs/splits/split"$splithalf"-geometry$counter.xyz > $temp

#changin specified atoms
        while read line;
        do
            line=$(( line + 2 ))
            sed -i "${line}s/C/H/" $temp
        done < $atomchangefile

# removing specified atoms
        while read line;
        do
            line=$(( line + 2 ))
            sed -i "${line}d" $temp
        done < $atomstorefile
    
        remainatoms=$( wc -l $temp | awk '{print $1}' )
        remainatoms=$(( remainatoms - 2 ))
        tail -n $remainatoms $temp > $tempp
        echo $remainatoms > "$filestoreloc"/split"$splithalf"-geometry$counter.xyz
        echo Comment Block >> "$filestoreloc"/split"$splithalf"-geometry$counter.xyz
        cat $tempp >> "$filestoreloc"/split"$splithalf"-geometry$counter.xyz
    
        splithalf=$(( splithalf + 1 ))
    done
    

    counter=$(( counter + 1 ))
done

我确信解决方案很简单。任何有关导致此问题的原因的见解将不胜感激。

标签: shellsed

解决方案


你破坏你的空格的原因是你需要引用你的字符串。但是一个更好的解决方案是将所有这些极其复杂的 shell 脚本重构为一个简单的sed或 Awk 脚本。

假设行号都表示原始输入文件中的行号,试试这个。

tmp=$(mktemp -t atomtmpXXXXXXXXX) || exit
trap 'rm -f "$tmp"' ERR EXIT

( sed 's%$%s/C/H/%' extract_internal/atomchange.txt
  sed 's%$%d%' extract_internal/atomremove.txt ) >"$tmp"

ls -l "$tmp"; nl "$tmp" # debugging

for file in "$basefilename"_xyzoutputs/splits/*; do
    dst= "$basefilename"_xyzoutputs/chops/${file#*/splits/}
    sed -f "$tmp" "$file" >"$dst"
done

这将两个输入文件组合成一个新sed脚本(值得注意的是,通过sed);调试行可让您检查结果(一旦您了解其工作原理,可能会删除它)。

您的问题并没有真正解释输入文件与输出文件的关系,所以我不得不猜测一下。重要的更改之一是避免sed -i在不修改现有文件时;但最重要的是,绝对避免使用sed -i.


推荐阅读