AWK新手技术问询:如何实现满足相邻行条件的目标行打印
Hi there! Let's break down how to fix your AWK script to meet your exact needs—since you're new to AWK, I'll explain each step clearly so you understand what's happening.
First, Let's Restate Your Requirement to Make Sure We're On the Same Page
We need to:
- Find every line where the 3rd field (
$3) equals"X" - Check if the very next line has its 2nd field (
$2) equal to"t1" - If both conditions are true, print the line that comes right before the "X" line
Your current script prints the line before any "X" line, but doesn't check the crucial "next line is t1" condition—so let's fix that.
The Solution: Track Previous Lines and Fields
AWK is great for processing text line-by-line, but to handle multi-line conditions, we need to save state from previous lines. Here's a script that does exactly what you need:
awk ' { # Roll our state variables forward: # Save the line before the previous line, then the previous line, etc. prev_prev_line = prev_line prev_line = $0 prev_3 = curr_3 curr_3 = $3 curr_2 = $2 # We can only start checking once we have at least 3 lines processed if (NR >= 3) { # Check if the previous line was an "X" line, and current line is "t1" if (prev_3 == "X" && curr_2 == "t1") { print prev_prev_line } } } ' your_input_file.txt
How This Works
Let's walk through the variables and logic:
prev_prev_line: Stores the line that's two positions before the current line (this is the line we'll print if conditions are met)prev_line: Stores the immediately preceding lineprev_3: Stores the 3rd field of the immediately preceding line (we use this to check if it's an "X" line)curr_3/curr_2: Store the 3rd and 2nd fields of the current line (to check if current line is "t1")
Every time we process a new line, we update these variables to "roll" forward. Once we've processed at least 3 lines (NR >=3), we check:
- Was the previous line an "X" line? (
prev_3 == "X") - Is the current line a "t1" line? (
curr_2 == "t1")
If both are true, we print prev_prev_line—which is exactly the line you want.
Testing Against Your Input
When we run this script on your sample input, it will output exactly what you expect:
w171930 t1 Y z2545377 w171931 t1 Y z2555698 w171932 t1 Y z2554345 w171933 t8 Y z6334512
It ignores the w171943 t1 line because the "X" line (w171943 t2 X) comes after it, not before—so the condition isn't triggered.
Why Your Original Script Didn't Work
Your original code saves any "Y" line, then prints it when it hits an "X" line. But it doesn't check what comes after the "X" line. Our script adds that crucial check by tracking the line after the "X" line and verifying it's a "t1" line.
A Slightly Alternative Version (Using Split)
If you prefer to work with full lines and split them into fields when needed, here's another version that does the same thing:
awk ' { prev_prev = prev prev = curr curr = $0 if (NR >= 3) { split(prev, prev_f) split(curr, curr_f) if (prev_f[3] == "X" && curr_f[2] == "t1") { print prev_prev } } } ' your_input_file.txt
This splits the previous and current lines into field arrays (prev_f and curr_f) to check the conditions. It works the same way, just uses split instead of storing individual fields upfront.
Content of the question comes from Stack Exchange, question author: aTarom

