我有一个文件input.txt
,其中包含以下格式的多个文件名。
FILENAME_DATE_LINENUMBER
,input.txt
包含许多这样的文件名。
文件名本身恰好有 5 个下划线。
FILE_NAME_1.DAT_20180123_4
FILE_NAME_2.DAT_20180123_5
FILE_NAME_3.DAT_20180123_6
FILE_NAME_4.DAT_20180123_7
所有文件都以input.txt
.我想解析input.txt
、迭代每个文件名并打印 FILENAME 和指定的行号(从 FILENAME )到output.txt
我知道将使用 sed 或 awk ,下面的命令可以完成这项工作。
awk 'FNR==LINENUMBER {print FILENAME, $0}' *.txt >output.txt
但是我如何遍历文件input.txt
并找到 FILENAME 并从 FILENAME 中提取 LINENUMBER 到output.txt
指定的 FILENAMEinput.txt
可以位于所在的子目录之一input.txt
。该位置的子目录之一(一级)内的 input.txt 中只能有一个具有 FILENAME 的文件input.txt
。
DIR
├── input.txt
│ ├── DIR1
│ │ ├── FILE_NAME_1.DAT
│ ├── DIR2
│ │ ├── FILE_NAME_2.DAT
│ ├── DIR3
│ │ ├── FILE_NAME_3.DAT
其中output.txt
应打印为
FILENAME
LINE( Extracted from FILENAME present in input.txt )
答案1
#!/bin/bash
do_one() {
# two args: $1=filename_no_dir $2=line_number
# Find the single filename
eval file=*"/$1"
echo $1
# $. == line number
perl -ne 'chomp; $.=='"$2"' and print "LINE($_)\n"' $file
}
export -f do_one
# Generate som test data
parallel 'mkdir DIR{}; seq 100 110 >DIR{}/FILE_NAME_{}.DAT' ::: {1..4}
# Test input.txt
cat <<EOF |
FILE_NAME_1.DAT_20180123_4
FILE_NAME_2.DAT_20180123_5
FILE_NAME_3.DAT_20180123_6
FILE_NAME_4.DAT_20180123_7
EOF
# Remove _YYYYMMDD.* to get filename, and .*_ to get line number
parallel do_one '{= s/_201\d\d\d\d\d.*// =}' '{= s/.*_// =}'
输出:
FILE_NAME_1.DAT
LINE(103)
FILE_NAME_2.DAT
LINE(104)
FILE_NAME_3.DAT
LINE(105)
FILE_NAME_4.DAT
LINE(106)
答案2
:> awk -F_ '{ print $1; print $3; }' inputfile
FILE1.DAT
4
FILE2.DAT
5
FILE3.DAT
6
FILE4.DAT
7
答案3
如果我理解正确的话
while IFS=_ read -r filename unuseddate linenum
do
printf "%s\n" "$filename"
sed -n "${linenum}{p;q}" */"$filename"
done < input.txt > output.txt
这会从 input.txt 中一次读取一行,并根据下划线将该行分成 3 部分。它打印文件名,然后触发 sed 命令(默认情况下不打印任何内容),然后在指定的行号上打印该行并退出 sed 的调用。文件名的位置应位于当前目录的直接子目录之一中。
然后所有输出都会重定向到output.txt。
答案4
GNU 的复杂解决方案parallel
+find
+awk
:
假设每个输入文件的内容类似于以下内容:
cat DIR1/FILE1.DAT_20180123_4
FILE1 a
FILE1 b
FILE1 c
FILE1 d
FILE1 e
FILE1 f
FILE1 g
因此,通过上述方案,文件中的第二行将FILE2.DAT_20180123_5
是FILE2 b
,文件中的第七行将是FILE4.DAT_20180123_7
- FILE4 g
。假设input.txt
文件与问题中的文件相同。
工作:
find . -type f -regextype posix-egrep -regex ".*/($(paste -s -d'|' input.txt))" \
| parallel -j0 "awk -v n="{=s/.*_//=}" -v fn="{/}" \
'NR==n{ print fn,\$0; exit }' {}" > output.txt
最终output.txt
内容:
$ cat output.txt
FILE4.DAT_20180123_7 FILE4 g
FILE3.DAT_20180123_6 FILE3 f
FILE1.DAT_20180123_4 FILE1 d
FILE2.DAT_20180123_5 FILE2 e