I think the method you're missing which efficiently performs this kind of logic is shift. Here's my proposal:
df_raw = df_raw.sort_index() # Optional, if index is not sorted
df_raw['A_is_zero'] = df_raw['A'] == 0
df_raw['prev_A_is_zero'] = df_raw['A_is_zero'].shift(1).fillna(True)
df_raw['next_A_is_zero'] = df_raw['A_is_zero'].shift(-1).fillna(False)
B_to_change = df_raw['A_is_zero'] & df_raw['next_A_is_zero'] & ~df_raw['prev_A_is_zero']
df_raw.loc[B_to_change, 'B'] = df_raw['B'].shift(-5).loc[B_to_change]
Since you didn't provide a sample dataframe I didn't test it though, so I can't guarantee it'll work, but I think I provided the main idea to reach the solution. For instance in the four rows before the last, if B_to_change is True, you'll get NaNs in 'B'. One other thing is that you're using .loc with integers, but I didn't know if your index is a range, in which case my first line is useless, or if it's not and you meant to use iloc (see this link about the loc / iloc difference), in which case my first line should be removed because it would not lead to the expected result.
EDIT:
my requirements has some iterative conditional sequential operations,
e.g.:
for i in range(1, len(df_raw)):
    if df_raw.loc[i, 'B'] != 0:
        df_raw.loc[i, 'A'] = df_raw.loc[i-1, 'A']
In this case (which you should have specified in your question), you can use forward filling as follows:
B_is_zero = df_raw['B'] == 0
df_raw['new_A'] = None
df_raw.loc[B_is_zero, 'new_A'] = df_raw.loc[B_is_zero, 'A'] 
df_raw['A'] = df_raw['new_A'].fillna(method='ffill')
Once again, you should be careful of how you handle the edge case where 'B' is nonzero on the first row.