다음과 같은 파일이 있다고 가정해 보겠습니다.
A 1
B 2
CC 33
다음과 같이 이전 파일의 두 가지 조합을 모두 포함하는 파일을 만들고 싶습니다.
AA 11
AB 12
ACC 133
BA 21
BB 22
BCC 233
CCA 331
CCB 332
CCCC 3333
임의의 파일에 대해 bash를 사용하여 이 작업을 수행할 수 있습니까? 각 항목에는 개행과 공백을 제외한 모든 문자가 포함될 수 있습니다. 일부 항목에는 UTF-8 문자가 포함됩니다.
나는 순서에 관심이 없습니다.
답변1
이 작업은 모두 셸에서 수행할 수 있습니다.
while read -r f1 f2
do
while read -r f3 f4
do
printf "%s %s\n" "$f1$f3" "$f2$f4"
done < your_file
done < your_file
IFS=" " read
"각 항목에는 줄 바꿈과 공백을 제외한 모든 문자가 포함될 수 있습니다." 항목에 탭 문자가 포함될 수 있다는 의미라면 대신에 read
(두 번) 이라고 말하세요 .
"세부":
이와 같은 명령은 read f1 f2
입력 줄의 첫 번째 "단어"를 변수로 f1
읽고나머지 줄입력하다 f2
. 예를 들어, 입력은 sum 을 The quick brown fox
생성합니다 . 파일에 3개(또는 그 이상) 열이 포함되지 않을 것이라고 확신하는 경우(즉, 한 줄에 2개 이상의 단어가 포함되지 않음) 걱정할 필요가 없습니다. 첫 번째 단어의 일부가 아닌 모든 항목이 두 번째 단어의 일부로 간주된다는 점에 만족한다면 위 코드는 문제가 없을 것입니다. f1="The"
f2="quick brown fox"
The quick brown fox
그러나 처리 f1="The"
되어 f2="quick"
무시 brown fox
(무시) 되려면 read
각 명령에 세 번째 변수를 추가하십시오. 예를 들어 ; f1 f2
가 됩니다 . 그러면 , 및 f1 f2 x
가 됩니다 . 그냥 사용하지 말고 두 번째 단어 이후의 입력을 삭제합니다. 두 번째도 마찬가지로 - 사용하지 않으므로 덮어써도 상관없습니다. 예를 들어 다른 일회성 변수를 사용하려는 경우 에도 가능합니다.f1="The"
f2="quick"
x="brown fox"
$x
read
read -r f3 f4 x
$x
… f3 f4 y
기본적으로 이 read
명령은 백슬래시( \
) 문자를 특별히 처리합니다. 기본적으로 백슬래시 뒤에 다른 문자가 오면 두 번째 문자의 특수 버전으로 병합됩니다. 그러나 더 중요한 것은 백슬래시 뒤에 공백이 오는 것은 단어 구분 기호로 간주되지 않으며, 백슬래시 뒤에 줄 바꿈(즉, 줄 끝의 백슬래시)은 줄 구분 기호/종료 기호로 간주되지 않는다는 것입니다 \C\C
. CC
. read
이 옵션을 호출하면 -r
옵션이 중지되고 백슬래시가 일반 문자가 됩니다. 다음은 차이점에 대한 몇 가지 실제적인 예입니다.
-r 없음(기본값) __ -r 사용 __ _입력_ f1 f2 f1 f2 A\B\\C AB\CA\B\\C D\EFDEFD\EF (또는 f2="E" 및 x="F") G\ (한 줄로 계산되지 않습니다.) G\ GH GH
그래서 답변의 첫 번째 버전에 마크업을 추가했습니다 -r
. 한 단어로 처리하고 싶다면 D\ E
사용하지 마세요 -r
.
답변2
awk
파일을 두 번 읽어 볼 수 있습니다 .
awk 'NR == FNR { m[$1] = $2; next; } { for (i in m) { print $1 i, $2 m[i]; } }' file file
답변3
순서를 유지하고 파일을 두 번 읽는 것을 방지하려면 다음을 수행합니다.
awk '{f1[NR] = $1; f2[NR] = $2}
END {
for (i = 1; i <= NR; i++)
for (j = 1; j <= NR; j++)
print f1[i]f1[j], f2[i]f2[j]
}' file
이제 전체 파일의 내용은 처리 전에 메모리에 저장됩니다(예:@taliezin의 접근 방식). 그렇게 하고 싶지 않다면 파일에 있는 줄 수만큼 파일을 읽어야 합니다.@G-Man의 방법. 그러나 / (awk
sh
bash
이것은 이것을 위해 설계되지 않았습니다)가 더 효율적일 것입니다.
awk '{f1=$1; f2=$2
while ((getline < "file") > 0) print f1$1, f2$2
close("file")}' file