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

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

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

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

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

  1. <ticket id="usa-001" REFUND="NO" TEST="TEST">
  2. <airline>Us Airlines</airline>
  3. <emptytag id="usa-001" REFUND="NO" TEST="TEST"/>
  4. <preis>30</preis><seat>
  5. <allseats>120</allseats>
  6. </ticket>

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

  1. et id="usa-001" REFUND="NO" TEST="TEST">
  2. <airline>Us Airlines</airline>
  3. <emptytag id="usa-001" REFUND="NO" TEST="TEST"/>
  4. <preis>30</preis><seat>
  5. <allseats>120</allseats>
  6. </ticket>
aydmsdu9

aydmsdu91#

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

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

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

  1. dd iflag=skip_bytes skip=5
jjjwad0x

jjjwad0x2#

使用GNU sed:

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

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

t5fffqht

t5fffqht3#

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

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

lawou6xi4#

您还可以使用tail

  1. # display from 4th byte
  2. # in other words, remove first 3 bytes
  3. $ printf 'apple\nbanana\nfig\ncherry\n' | tail -c +4
  4. le
  5. banana
  6. fig
  7. cherry
91zkwejq

91zkwejq5#

使用cut

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

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

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

z9gpfhce6#

你知道,你也可以用hexdump

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

tzcvj98z7#

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

  1. 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-

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

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

  1. dd bs=1 skip=100 < infile > outfile

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

  1. tail -c +101 infile # start at byte 101, having skipped the first 100
展开查看全部
ygya80vv

ygya80vv8#

如果你知道这是ASCII

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

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

  1. printf '%s' "${test_input}" | gnu-wc -lcm
  1. ꜜ&$Ꝡ*&꟠.(ꢔ2*ꥴ6,꩸:.ꮘ>0B2F4J6N8R:다V<돨Z>듈^@땼bBfDjF
  1. 0 54 90
  1. mawk2 'BEGIN {
  2. FS = "^" (_=(_="([\\000-\\177]|" \
  3. "[\\302-\\364][\\200-\\277]+)")(_=(_)_)_
  4. OFS = ORS =__=""
  5. _+=_^= RS = "^$" } __!= $(NF *=_==NF )' | gnu-wc -lcm
  1. 0 49 81
展开查看全部

相关问题