在Bash Unix中从文本文件中删除前n个字符

hmtdttj4  于 2022-10-17  发布在  Unix
关注(0)|答案(8)|浏览(237)

我正在尝试从文本文件中删除前N个字符,重要的是不是逐行删除。
目前,我编写的这段代码删除了每行中的“I”个字符。但我想从整个文本中删除。

for FILE in *; 
    do  x=$(wc -c < "$FILE"); for ((i=1; i <= $x; ++i));
            do sed "s/^.\{$i\}//" $FILE > $i; 
        done;
done;

例如,我在目录xml/root.xml中有这个XML文件

<ticket id="usa-001" REFUND="NO" TEST="TEST">
        <airline>Us Airlines</airline>
        <emptytag id="usa-001" REFUND="NO" TEST="TEST"/>
        <preis>30</preis><seat>
            <allseats>120</allseats>
</ticket>

我想要的是删除前N个字符并将其保存到一个新文件中。我们就说5个吧,就这么定了

et id="usa-001" REFUND="NO" TEST="TEST">
        <airline>Us Airlines</airline>
        <emptytag id="usa-001" REFUND="NO" TEST="TEST"/>
        <preis>30</preis><seat>
            <allseats>120</allseats>
</ticket>
aydmsdu9

aydmsdu91#

如果您真的只想过滤掉文件的前n个字符,那么您需要的工具是dd,它允许您指定要跳过的块数。如果希望块大小为1,请使用bs进行指定。例如,要跳过输入文件的前2个字符,请使用:

$ echo foobarbaz | dd bs=1 skip=2 2> /dev/null
obarbaz

您可以使用if指定输入文件,但重定向可能更简单。dd向stderr写入一系列诊断信息,输出重定向只是为了抑制这些消息。这将是非常慢的,因为块大小非常小,但是(如果您有支持这一点的dd),您可以使用以下命令比sed快得多:

dd iflag=skip_bytes skip=5
jjjwad0x

jjjwad0x2#

使用GNU sed:

$ sed -Ez 's/^.{5}//' root.xml > 5
$ cat 5
et id="usa-001" REFUND="NO" TEST="TEST">
        <airline>Us Airlines</airline>
        <emptytag id="usa-001" REFUND="NO" TEST="TEST"/>
        <preis>30</preis><seat>
            <allseats>120</allseats>
</ticket>

如果要在少于5个字符的文件中删除最多5个字符,请使用{1,5},而不是{5}

t5fffqht

t5fffqht3#

使用您显示的样例,请尝试以下awk代码。在GNU awk中编写和测试。

  • 单输入文件:*
awk -i inplace -v RS='^.{5}' -v ORS='' 'END{print}'  Input_file
  • 对于带有GNU awk的多个输入文件*:这里使用ENDFILE函数,该函数将按照名称处理每个输入文件末尾的所有行。
awk -i inplace -v RS='^.{5}' -v ORS='' 'ENDFILE{print}' *
lawou6xi

lawou6xi4#

您还可以使用tail


# display from 4th byte

# in other words, remove first 3 bytes

$ printf 'apple\nbanana\nfig\ncherry\n' | tail -c +4
le
banana
fig
cherry
91zkwejq

91zkwejq5#

使用cut

n=5; cut -c$n- file.txt

看起来您想要将每一行都保存在一个文件中。

n=5; cut -c$n- file.txt | awk '{print $0 > NR}'
n=5; cut -c$n- file.txt | awk '{print $0 > NR; exit}'
z9gpfhce

z9gpfhce6#

你知道,你也可以用hexdump

hexdump -s 5 -ve '/1 "%c"' inputfile > outfile
tzcvj98z

tzcvj98z7#

你可以*做一些像这样的粗俗和丑陋的事情-

awk 'BEGIN{ left=100 } { if (left>0) { len=length($0); if (len<left) { left-=len+1; next } else {  print substr($0,left); len=0; next } } else print $0 }' infile

请不要这样。改用Ed的sed
你可以用Perl-

perl -e 'seek(STDIN,100,0) && print <>' < infile # simpler
perl -e '$/=undef; open(my $fh,$ARGV[0]); seek($fh,100,0) && print <$fh>' infile # cleaner

但是William的dd可以在二进制文件上运行,不需要任何代码...

dd bs=1 skip=100 < infile > outfile

如果您的版本理解+选项,SunDeep的可能是最适合文本文件的-

tail -c +101 infile # start at byte 101, having skipped the first 100
ygya80vv

ygya80vv8#

如果你知道这是ASCII

jot -s '' 27 | gsed -zE 's/.{15}/&\n/g; s/[\n]+$/\n/g'
123456789101112
131415161718192
021222324252627
mawk 5 RS='^.....' ORS=
6789101112
131415161718192
021222324252627

假设它符合UTF-8文本,那么这应该可以清理最多5个任何类型的Unicode字符,包括换行符:

printf '%s' "${test_input}" | gnu-wc -lcm
ꜜ&$Ꝡ*&꟠.(ꢔ2*ꥴ6,꩸:.ꮘ>0곌B2긌F4꽐J6낐N8뇄R:다V<돨Z>듈^@땼bB뗼fD뙀jF
0      54      90
mawk2 'BEGIN { 
    FS = "^"  (_=(_="([\\000-\\177]|" \
         "[\\302-\\364][\\200-\\277]+)")(_=(_)_)_ 

   OFS = ORS =__="" 
   _+=_^= RS = "^$" } __!= $(NF *=_==NF )' | gnu-wc -lcm
0      49      81

相关问题