이 입력이 있습니다.
array='2 0.00000 -1.45191
6 0.81778 -0.63413
10 0.85020 -0.60170
8 1.40260 -0.04931
22 3.25781 1.80590
20 4.32051 2.86860
6 0.00000 -0.93906
18 0.07618 -0.86288
8 0.36922 -0.56984
12 0.71195 -0.22711
16 0.88517 -0.05389'
동일한 배열을 복사하려고 하는데 아래와 같이
2 0.00000 -1.45191
6 0.81778 -0.63413
10 0.85020 -0.60170
8 1.40260 -0.04931
22 3.25781 1.80590
20 4.32051 2.86860
6- 0.00000 -0.93906
18- 0.07618 -0.86288
8- 0.36922 -0.56984
12- 0.71195 -0.22711
16- 0.88517 -0.05389
차이점은 $1
첫 번째 필드의 두 번째 부분 0.00000
에는 두 번째 필드의 두 번째 값을 표시자로 사용하여 접미사가 붙는다는 점입니다. $2
이 명령을 사용할 수 있다면 awk
기쁠 것입니다 .
답변1
귀하의 예를 바탕으로 귀하는나타나다원하는 것은 두 번째 열에 0.00000
문자열(또는 숫자 값)의 발생 횟수를 기록하고 개수가 2에 도달할 때 첫 번째 열의 값에 추가하는 것입니다.0
-
printf '%s\n' "$array" | awk '$2 == "0.00000" {++ind} ind == 2 {$1 = $1"-"} 1'
그러나 이는 조건을 충족하는 레코드의 열 구분 기호를 기본(단일 공백) 출력 구분 기호로 바꿉니다.만약에입력 구분 기호는 일련의 공백 문자이므로 정렬을 유지하는 한 가지 방법은 첫 번째 공백 문자를 다음으로 바꾸는 것입니다 -
.
$ printf '%s\n' "$array" | awk '$2 == "0.00000" {++ind} ind == 2 {sub(/ /,"-")} 1'
2 0.00000 -1.45191
6 0.81778 -0.63413
10 0.85020 -0.60170
8 1.40260 -0.04931
22 3.25781 1.80590
20 4.32051 2.86860
6- 0.00000 -0.93906
18- 0.07618 -0.86288
8- 0.36922 -0.56984
12- 0.71195 -0.22711
16- 0.88517 -0.05389
답변2
이전 질문에 따르면 탭으로 구분된 입력이 있는 것 같습니다. 다음을 시도해 보세요.
$ printf '%s\n' "$array" | awk 'BEGIN{FS=OFS="\t"} ($2==0) && c++{s="-"} {$1=$1 s} 1'
2 0.00000 -1.45191
6 0.81778 -0.63413
10 0.85020 -0.60170
8 1.40260 -0.04931
22 3.25781 1.80590
20 4.32051 2.86860
6- 0.00000 -0.93906
18- 0.07618 -0.86288
8- 0.36922 -0.56984
12- 0.71195 -0.22711
16- 0.88517 -0.05389
또한 위의 내용은 0
세 번째 또는 그 이후의 값이 열 2에 발생하는 경우 여전히 -
열 1에 s를 추가한다고 가정합니다.
답변3
awk
다음과 같은 방법으로 해결할 수 있습니다 .
printf '%s\n' "$array" |
awk -F '\t' 'BEGIN{OFS=FS}
($2 ~ /^0\.0+$/ && ++k==2),0 {
$1 = $1 "-"
}1' -
- 우리는 범위 연산자를 사용합니다
,
- 범위 연산자는 처음에는 false입니다. 왼쪽 피연산자가 true로 평가되면 범위는 true가 되고 오른쪽 피연산자가 true로 평가될 때까지 true로 유지됩니다.
- 왼쪽 피연산자는
$2 ~ /^0\.0+$/ && ++k==2
- 따라서 두 번째 열이 부동 소수점 0이고 이것이 두 번째로 발생하면 true로 평가됩니다.
- 그 후 범위 연산자는 오른쪽이 true(우리의 경우 0)로 평가될 때까지 true를 유지하므로 절대 발생하지 않습니다.
- IOW, 두 번째 열의 0이 있는 행부터 eof까지의 범위는 true입니다.
- 범위 내의 작업에는 첫 번째 필드 뒤에 대시가 붙습니다.
- 외로운1필드 중 하나를 건드렸으므로 재구성된 $0는 TAB(OFS)를 사용하여 필드를 연결하여 STDOUT에 인쇄되어야 합니다.
GNU sed
-E
정규식 작성을 단순화하려면 확장 정규식 모드( )를 사용하십시오 .
printf '%s\n' "$array" |
sed -E '
0,/^[^\t]+\t+0\.0+(\t|$)/b
//,$s/\t/-&/
' -
/^[^\t]+\t+0\.0+(\t|$)/
두 번째 필드가 0인 행을 선택하는 정규식 입니다.- 첫 번째 범위는 행 번호 0부터 두 번째 열에서 처음으로 나타나는 0까지의 행을 선택합니다. 이 모든 줄은 수정되지 않은 채 STDOUT으로 전달됩니다.
- 다음 번, 두 번째에는 두 번째 열에서 eof까지 0이 표시됩니다. 여기서 첫 번째 공백 문자를 대시로 변경합니다. 이는 줄에 선행 공백이 없다고 가정합니다.
- 이 두 범위에 속하지 않는 다른 줄은 수정되지 않은 채 STDOUT으로 전달됩니다.
- 0번째 줄 번호는 귀하의 경우와 같이 정규식이 첫 번째 줄과 일치하는 경우를 처리하기 위한 GNU sed 확장입니다.
산출:
2 0.00000 -1.45191
6 0.81778 -0.63413
10 0.85020 -0.60170
8 1.40260 -0.04931
22 3.25781 1.80590
20 4.32051 2.86860
6- 0.00000 -0.93906
18- 0.07618 -0.86288
8- 0.36922 -0.56984
12- 0.71195 -0.22711
16- 0.88517 -0.05389