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



我正在尝试从文本文件中删除前 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>

如果您真的只想过滤掉文件的前 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

使用 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}

你也可以使用tail

# display from 4th byte
# in other words, remove first 3 bytes
$ printf 'applenbanananfigncherryn' | tail -c +4
le
banana
fig
cherry

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

对于单Input_file:

awk -i inplace -v RS='^.{5}' -v ORS='' 'END{print}'  Input_file

对于具有GNUawk的多个Input_file:在此处使用ENDFILE函数,该函数将按照名称处理每个Input_file末尾的所有行。

awk -i inplace -v RS='^.{5}' -v ORS='' 'ENDFILE{print}' *

withcut

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}'

你知道,你也可以使用hexdump

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

你可以做一些像这样丑陋和丑陋的事情——

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

但是威廉的dd在不需要任何代码的情况下处理二进制文件......

dd bs=1 skip=100 < infile > outfile 

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

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

如果你知道它是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
    

最新更新