提取配对线

提取配对线

我有一个这样的txt文件。有成对的线email-passwordemail-hash

EMAIL:[email protected]
PASSWORD:pass1
EMAIL:[email protected]
PASSWORD:pass2
EMAIL:[email protected]
PASSWORD:pass3
EMAIL:[email protected]
HASH:qwerty123
EMAIL:[email protected]
HASH:somehash
EMAIL:[email protected]
PASSWORD:pass6

我尝试仅提取email-password不包含email-hash行的行。在我的情况下该命令无法正常工作sed -e 's/.*EMAIL://' -e 's/.*PASSWORD://' -e "/\b\HASH\b/d" test.txt

期望输出:

[email protected]
pass1
[email protected]
pass2
[email protected]
pass3
[email protected]
pass6

答案1

sed -n 'N;s/^EMAIL://;s/PASSWORD://p' file
  • N将下一行追加到模式空间,
  • s/^EMAIL://不用任何东西代替EMAIL:
  • s/PASSWORD://p没有任何东西替代PASSWORD:并且仅在替换成功时打印

在样本输入上进行测试。假设:第一行是EMAIL:,第二行是PASSWORD:or HASH:,然后重复。


作为奖励,如果可能有空行,最好使用 awk,

awk -F ':' '/^PASSWORD:/{print line;print $2}/^EMAIL:/{line=$2}' file

答案2

项目管理识别 如您所知 sed 是一个面向行的流编辑器,因此当打印或不打印的决定取决于另一行(就像您的情况一样)时,我们需要编排一个状态机,在这种情况下它们将需要触发器或变量。

本质上,我们需要暂停打印,直到看到正确的状态转换。就像在本例中一样,当我们仅从状态(电子邮件行)->状态(密码行)转换时。

GNU sed在扩展正则表达式模式下使用-E,这使得阅读 sed 代码更容易,并且编写它时不易出现反斜杠。

$ sed -Ee '
    /^PASSWORD:/!{h;d;}
    x;G;s/(^|\n)[^:]*:/\1/g
' test.txt

基本思想是将不是密码行的行保存在保持寄存器中,以便当我们实际到达密码行时我们可以使用它。

使用GNU awk我们基本上在 awk 中编写上述 sed 功能,并使用 awk 变量 e 作为保持寄存器。

$ awk -F: '
    /^PASSWORD:/&&
    ($0=e RS $2)"";{e=$2}
' test.txt

使用GNU grepbefore 选项-B在密码行之前列出一行,然后删除 grep 生成的虚线并假设没有人使用它作为密码。

$ < test.txt \
  grep -B1 '^PASSWORD:' |
  grep -Fxve -- | cut -d: -f2-

perl当我们选择下一行然后进行检查时可以如图所示使用。

$ perl -ne '
    /^EMAIL:/ && ($_ .= <>);
    /\nPASSWORD:/ && print(s/^[^:]+://mgr);
' tes.txt

bash 内置函数

while IFS=: read -r a p; do
  case $a in
    'PASSWORD') printf '%s\n' "$e" "$p" ;;
    *) e=$p ;;
  esac
done < test.txt

答案3

这是另外几个变体:

paste -d :  - - < myfile | awk -F: '$3 == "PASSWORD" {print $2; print $4}'
tac myfile | awk -F: '$1 == "PASSWORD" {print $2; getline; print $2}' | tac

答案4

如果该文件始终采用该格式,并EMAIL在每隔一行的开头:

sed -n 'N;s/^EMAIL:\(.*\n\)PASSWORD:/\1/p'

应该这样做。或者,为了安全起见,请查找EMAIL:记录的开头:

sed -n '/^EMAIL:/{N;s/^EMAIL:\(.*\n\)PASSWORD:/\1/p;}'

您还可以使用pcregrep其多行模式:

pcregrep -M -o1 -o2 --om-separator=$'\n' '^EMAIL:(.*)\nPASSWORD:(.*)'

相关内容