我是linux新手,也是脚本新手。我在使用bash的linux环境中工作。我需要做以下事情: 1.逐行读取txt文件 2.删除第一行 3.在第一行之后删除每行的中间部分 4.将更改复制到新的txt文件
第一行之后的每一行有三个部分,第一部分总是以.pdf结尾,第三部分总是以R0开头,但中间部分没有一致性。
文件中的2行示例:
R01234567_High Transcript_01234567.pdf High School Transcript R01234567 R01891023_Application_01891023127.pdf Application R01891023
这是我到目前为止所拥有的。我只是阅读文件,将其打印到屏幕并将其复制到另一个文件。
#! /bin/bash
cd /usr/local/bin;
#echo "list of files:";
#ls;
for index in *.txt;
do echo "file: ${index}";
echo "reading..."
exec<${index}
value=0
while read line
do
#value='expr ${value} +1';
echo ${line};
done
echo "read done for ${index}";
cp ${index} /usr/local/bin/test2;
echo "file ${index} moved to test2";
done
所以我的问题是,如何在.pdf之后但在R0之前删除每一行的中间位??
答案 0 :(得分:2)
使用sed
:
sed 's/^\(.*\.pdf\).*\(R0.*\)$/\1 \2/g' file.txt
这将移除.pdf
和R0
之间的所有内容,并将其替换为单个空格。
您的示例的结果:
R01234567_High Transcript_01234567.pdf R01234567
R01891023_Application_01891023127.pdf R01891023
答案 1 :(得分:1)
由于有一个制表符分隔符,所以这对于awk来说很简单。借用我最初删除的答案和@ geek1011删除答案:
awk -F"\t" '{print $1, $NF}' infile.txt
此处awk
按标签拆分文件中的每条记录,然后打印第一个字段$1
和最后一个字段$NF
NF
内置{{1} }}变量用于记录的字段数;通过预先加上一个美元符号,它会显示“记录中最后一个字段的值”。
留下这个,以防有人像我原先假设的那样有空格分隔。
您可以使用awk
代替使用bash来阅读文件:
awk
awk 'NR>1{for(i=1; $i!~/pdf/; ++i) firstRec=firstRec" "$i} NR>1{print firstRec,$i,$NF}' yourfile.txt
逐行读取文件并处理它遇到的每条记录。字段由空格自动分隔。第一个字段是awk
,第二个字段是$1
,依此类推。 $2
内置了变量;这里我们使用awk
这是记录中包含的字段数,NF
是当前正在处理的记录号。
此脚本执行以下操作:
NR
)。将我们找到的所有内容存储到名为$i!~/pdf/
的变量中的该字段,并以空格(firstRec
)分隔。firstRec=firstRec" "$i
,然后打印出我们停止迭代的任何字段(包含“pdf”的字段)firstRec
,最后打印出记录中的最后一个字段,是$i
($NF
)您可以将此指向另一个文件:
print firstRec,$i,$NF
awk 'NR>1{for(i=1; $i!~/pdf/; ++i) firstRec=firstRec" "$i} NR>1{print firstRec,$i,$NF}' yourfile.txt > outfile.txt
可能是一种更清晰的方式,因为如果您的sed
文件有多个空格分隔字符,那么您将丢失多个空格。
答案 2 :(得分:1)
它有点冗长,并且很多比我们知道字段被制表符文字分隔的意义更简洁和有效,但是以下循环在纯本机bash中执行此处理没有外部工具:
shopt -s extglob
while IFS= read -r line; do
[[ $line = *".pdf"*R0* ]] || continue # ignore lines that don't fit our format
filename=${line%%.pdf*}.pdf
id=R0${line##*R0}
printf '%s\t%s\n' "$filename" "$id"
done
${line%%.pdf*}
返回行中第一个.pdf
之前的所有内容; ${line%%.pdf*}.pdf
然后将.pdf
附加到该内容。
同样,${line##*R0}
扩展到最后R0
之后的所有内容; R0${line##*R0}
因此扩展到以R0
开头的最终字段(假设这是文件中该字符串的唯一实例)。
如果cat -t file
(在MacOS上)或cat -A file
(在Linux上)在字段之间显示^I
序列(但不在字段内),请改用以下内容:
while IFS=$'\t' read -r filename title id; do
printf '%s\t%s\n' "$filename" "$id"
done
这会将三个制表符分隔的字段读入名为filename
,title
和id
的变量,并发出filename
和id
字段。
答案 3 :(得分:0)
您可以在每个sed
上使用line
,如下所示:
line="R01234567_High Transcript_01234567.pdf High School Transcript R01234567"
echo "$line" | sed 's/\.pdf.*R0/\.pdf R0/'
# output
R01234567_High Transcript_01234567.pdf R01234567
这会使用空格键替换.pdf
和R0
之间的任何内容。
它没有处理一些边缘情况,但它简单明了