Linux Bash脚本为每个输入行编写2个具有不同输出元素的文件

Linux Bash脚本为每个输入行编写2个具有不同输出元素的文件,linux,bash,sed,Linux,Bash,Sed,我想使用bash脚本将1个输入文件处理为2个输出文件,每个文件包含与输入文件相同的行数,但输入行的不同部分。特别是其中一个输出文件必须包含输入行选择的md5hash,hash是按行计算的,而不是按文件计算的!: 所以 Input_file.txt:*3个字段,用空格分隔 输出文件_1.txt必须如下所示:左字段是MD5sum,右字段是输入文件中的字段3,该文件也包含在MD5hash中: 12df5j754G75f738fjk3483df3fdf9 1verylongalpha1234numeri

我想使用bash脚本将1个输入文件处理为2个输出文件,每个文件包含与输入文件相同的行数,但输入行的不同部分。特别是其中一个输出文件必须包含输入行选择的md5hash,hash是按行计算的,而不是按文件计算的!:

所以

Input_file.txt:*3个字段,用空格分隔

输出文件_1.txt必须如下所示:左字段是MD5sum,右字段是输入文件中的字段3,该文件也包含在MD5hash中:

12df5j754G75f738fjk3483df3fdf9 1verylongalpha1234numeric1

3jf75j47fh4G84ka9J884hs355jhd8 2verylongalpha1234numeric2

4hf7dn46chG4875ldgkk348fk345d9 3verylongalpha1234numeric3
输出文件_2.txt必须如下所示:输入文件+MD5HASH中的field1和field2

12347654 abcdfg 12df5j754G75f738fjk3483df3fdf9

34543673 nvjfur 3jf75j47fh4G84ka9J884hs355jhd8

75868643 vbdhde 4hf7dn46chG4875ldgkk348fk345d9
我已经有了一个脚本来完成这项工作,但它的性能非常差:下面的脚本可能无法工作,这是我的想法,这里没有linux,我写这个,对不起

#!/bin/bash

While read line

do   MD5_HASH=${sed -nr 's/^[[:digit:]]*\s[[:alpha:]]*\s([[:alnum:]]*)/\1/p' <<<$line     | md5sum} 
read $line DATA_PART1 DATA_PART2 DATA_PART3

echo "$MD5_HASH $DATA_PART3" >> file_1.txt    ##append file_2.txt in loop THIS IS WHERE IT GETS HORRIBLY SLOW!

echo "$DATA_PART1 $DATA_PART2 $MD5_HASH" 
done < input_file.txt > file_2.txt

exit 0
我认为将stdout重定向到带有append构造“>>”的文件是性能低下的原因,但我想不出其他方法。它在循环中,因为我必须计算每行的md5hash

哦,sed命令是必要的,因为实际上进入MD5SUM的部分只能用regex和一个相当复杂的模式捕获


有人有什么建议吗?

在这种情况下,我会使用功能齐全的语言,比如Python

尽管您可能会通过仅使用标准gnu工具找到实现这一点的方法,但最终很可能会得到一个解决方案:

非常复杂,难以阅读和维护 效率低下,因为这些工具没有提供直接的方法来实现这一点。 1.在Python中创建第一个文件 2.在Python中创建第二个文件 我不确定您在哪些字段上计算校验和;然而,当然,你可以在你想要的任何字段上计算它;您还可以对行执行更复杂的基于regexp的匹配;您可以通过一次输出两个文件来加快速度,从而避免两次计算md5

3.同时创建两个文件 4.与1相同,但从标准输入读取
在这种情况下,我会使用功能齐全的语言,比如Python

尽管您可能会通过仅使用标准gnu工具找到实现这一点的方法,但最终很可能会得到一个解决方案:

非常复杂,难以阅读和维护 效率低下,因为这些工具没有提供直接的方法来实现这一点。 1.在Python中创建第一个文件 2.在Python中创建第二个文件 我不确定您在哪些字段上计算校验和;然而,当然,你可以在你想要的任何字段上计算它;您还可以对行执行更复杂的基于regexp的匹配;您可以通过一次输出两个文件来加快速度,从而避免两次计算md5

3.同时创建两个文件 4.与1相同,但从标准输入读取
您可以从bash同时写入这两个文件,如下所示:

; function to remove extraneous filename output from md5sum.  omit on 
; OS X, which has 'md5' command that already works this way.
md5() { set -- $(md5sum "$@"); echo "$1"; }

exec 3>file_1.txt 4>file_2.txt
while read left middle right; do
  md5="$(echo -n "$right" | md5)"
  echo >&3 "$md5 $right"
  echo >&4 "$left $middle $md5"
done <input_file.txt
exec 3>&- 4>&-
<input_file.txt perl split.pl

您可以从bash同时写入这两个文件,如下所示:

; function to remove extraneous filename output from md5sum.  omit on 
; OS X, which has 'md5' command that already works this way.
md5() { set -- $(md5sum "$@"); echo "$1"; }

exec 3>file_1.txt 4>file_2.txt
while read left middle right; do
  md5="$(echo -n "$right" | md5)"
  echo >&3 "$md5 $right"
  echo >&4 "$left $middle $md5"
done <input_file.txt
exec 3>&- 4>&-
<input_file.txt perl split.pl

无法计算出要为哪个字符串计算md5,此一行在整行上执行此操作,并在“file1”和“file2”中按您的意愿输出处理后的“input_file”:

awk '{ "md5 -q -s \""$0"\"" | getline md5; 
     print md5" "$3 > "file1"; 
     print $1" "$2" "md5 > "file2" }' input_file

希望有帮助。

无法计算出要计算md5的字符串,这一行在整行上进行计算,并在“文件1”和“文件2”中按您的意愿输出处理后的“输入文件”:

awk '{ "md5 -q -s \""$0"\"" | getline md5; 
     print md5" "$3 > "file1"; 
     print $1" "$2" "md5 > "file2" }' input_file

希望对您有所帮助。

您可以通过管道和并联提高效率

根据伪代码,您需要最后一个元素的md5和:

paste -d ' '     \
  input_file.txt \
  <(cut -d' ' -f3 input_file.txt | parallel echo '{}' \| md5sum | cut -d' ' -f1) |
  awk '{ print $4, $3 > "file_1.txt"; print $1, $2, $4 > "file_2.txt" }'
文件2.txt


您可以使用管道和平行管道来提高效率

根据伪代码,您需要最后一个元素的md5和:

paste -d ' '     \
  input_file.txt \
  <(cut -d' ' -f3 input_file.txt | parallel echo '{}' \| md5sum | cut -d' ' -f1) |
  awk '{ print $4, $3 > "file_1.txt"; print $1, $2, $4 > "file_2.txt" }'
文件2.txt


可以稍微整理一下bash脚本。请注意,read命令可以将3个字段读入单独的变量:

#!/bin/bash
rm -f file_1.txt file_2.txt    
While read f1 f2 f3; do
    hash=$(md5sum <<< $f3)
    printf "%s %s\n" "$hash" "$f3" >> file_1.txt
    printf "%s %s %s\n" "$f1" "$f2" "$hash" >> file_2.txt
done < input_file.txt

可以稍微整理一下bash脚本。请注意,read命令可以将3个字段读入单独的变量:

#!/bin/bash
rm -f file_1.txt file_2.txt    
While read f1 f2 f3; do
    hash=$(md5sum <<< $f3)
    printf "%s %s\n" "$hash" "$f3" >> file_1.txt
    printf "%s %s %s\n" "$f1" "$f2" "$hash" >> file_2.txt
done < input_file.txt

您的代码不完整,循环体未使用“完成”关闭。请更正它并将代码格式化为代码块,而不是引用我已经为您更改了文件示例的格式,请对codeLev执行相同的操作,“完成”在那里,但几乎不可见。我将尝试格式化代码块。Me的第一个计时器您的代码不完整,循环体未使用done关闭。请更正它并将代码格式化为代码块,而不是引用我已经为您更改了文件示例的格式,请对codeLev执行相同的操作,“完成”在那里,但几乎不可见。我将尝试格式化代码块。meNice解决方案的第一个计时器,尽管我在这里对10k行结果进行了快速基准测试,而且正如我之前猜测的那样,Python解决方案的速度要快得多。。65ms vs 12399ms.顺便说一句,在计算校验和之前,你应该去掉$right结尾的换行符。.是的,任何避免分叉的解决方案

每个校验和计算的md5sum拷贝将快得多。但是性能,而不是所谓的复杂性,是切换语言的原因。在bash中仍然很容易,只是速度慢而已新行是一个很好的观点,经过编辑。我在考虑awk,但我不确定它是否有任何计算md5的内容;如果是这样,那就太好了。。每行生成一个进程只适用于非常少量的行,这样效率会非常低。是的,您可能需要使用perl或python或ruby或。。。如果您想要性能,这是一个不错的解决方案,尽管我在这里对10k行的结果进行了快速基准测试,正如我之前猜测的那样,Python解决方案的速度要快得多。。65ms vs 12399ms..顺便说一句,在计算校验和之前,您应该去掉$末尾的换行符..是的,任何避免在每次校验和计算中分叉md5sum新副本的解决方案都会快得多。但是性能,而不是所谓的复杂性,是切换语言的原因。在bash中仍然很容易,只是速度慢而已新行是一个很好的观点,经过编辑。我在考虑awk,但我不确定它是否有任何计算md5的内容;如果是这样,那就太好了。。每行生成一个进程只适用于非常少量的行,这样效率会非常低。是的,您可能需要使用perl或python或ruby或。。。如果你想要性能。谢谢,我对Python不太了解,但是在每个文件的解决方案中,outfile声明在哪里?或者在Python脚本之外完成,比如./Python_script.py>outfile.txtyes,在两个单文件解决方案中,所有输出都写在标准输出上;如果要直接写入文件,请在with语句中添加一个open'out1.txt',w'as out1,如第三个示例所示。谢谢,我喜欢Python。我会做一个关于它的速成课程,因为它在我看来非常强大。事实上。。如果您感兴趣,在本月的linux杂志上有一篇文章专门介绍用Python脚本替换bash实用程序脚本,这可能是一个很好的起点。谢谢,我不太了解Python,但是在每个文件的解决方案中,outfile声明在哪里?或者在Python脚本之外完成,比如./Python_script.py>outfile.txtyes,在两个单文件解决方案中,所有输出都写在标准输出上;如果要直接写入文件,请在with语句中添加一个open'out1.txt',w'as out1,如第三个示例所示。谢谢,我喜欢Python。我会做一个关于它的速成课程,因为它在我看来非常强大。事实上。。如果您感兴趣,在本月发行的linux杂志上有一篇文章专门介绍用Python脚本替换bash实用程序脚本,这可能是一个很好的起点。请注意,使用getline意味着awk仍在分出一个外部进程来计算每个校验和,因此,这并不是一个对shell解决方案的效率胜利。我认为您必须将“openssl”放在“md5”语句之前。请注意,使用getline意味着awk仍然需要外部进程来计算每个校验和,因此这并不是对shell解决方案的效率胜利。我认为您必须将“openssl”放在“md5”语句之前。like可以在这个主题中阅读:我喜欢你的bash替代方案。决定选择Python选项和性能,尽管我喜欢您的bash替代方案。但是决定使用Python选项和性能
765ac5d0002aed1141a6a4e7b90e4ac9 1verylongalpha1234numeric1
b31901def07d436aed2c8028b2efa4ec 2verylongalpha1234numeric2
0722a6e50f6f8726f9754e7f71f9ad2c 3verylongalpha1234numeric3
12347654 abcdfg 765ac5d0002aed1141a6a4e7b90e4ac9
34543673 nvjfur b31901def07d436aed2c8028b2efa4ec
75868643 vbdhde 0722a6e50f6f8726f9754e7f71f9ad2c
#!/bin/bash
rm -f file_1.txt file_2.txt    
While read f1 f2 f3; do
    hash=$(md5sum <<< $f3)
    printf "%s %s\n" "$hash" "$f3" >> file_1.txt
    printf "%s %s %s\n" "$f1" "$f2" "$hash" >> file_2.txt
done < input_file.txt