개별 출력 라인을 변수에 저장

개별 출력 라인을 변수에 저장

저는 이 기능을 사용하여 find -mtime -2지난 24시간 이내에 수정된 파일을 찾습니다. 출력은 다음과 같습니다.

/home/user/logs/file-2014-08-22.log
/home/user/logs/file-2014-08-23.log

출력의 첫 번째 줄을 변수에 저장한 다음 두 번째 줄을 별도의 변수에 저장해야 합니다. 그냥 놔둘 수가 없어요. 나는 당신이 무엇을 제안하고 있는지 알고 있지만 | grep 22이것은 23여러 번 실행될 bash 스크립트의 일부이며 다음에 다른 이름을 가진 파일 세트가 있을 것이므로 grep너무 구체적입니다. 이것이 가능 합니까 awk? 그렇다면 어떻게 해야 할까요? .

답변1

파일 이름에 공백 등이 없다고 가정하면 이를 수행하는 몇 가지 방법이 있습니다. 하나는 배열을 사용하는 것입니다.

files=( $(find -mtime -2) )
a=${files[1]}
b=${files[2]}

filesfind모든 경로 출력의 배열이 순서대로 배열되며 0부터 시작하여 색인이 지정됩니다. 원하는 행을 얻을 수 있습니다. 여기서는 두 번째와 세 번째 행을 aand 에 저장 b하지만 배열 요소를 직접 사용할 수도 있습니다.

해당 옵션을 사용하는 GNU find 또는 다른 대안이 있는 경우 다음 printf과 함께 사용하는 것입니다.read그리고프로세스 교체:

read junk a b junk < <(find -printf '%p ')

이는 find모든 출력을 한 줄로 변환한 다음 해당 줄을 input 으로 공급하여 read첫 번째 단어(경로)를 junk,두 번째 단어 에 저장하고 a, 세 번째 단어를 저장하고 b줄의 나머지 부분을 저장하여 junk반복합니다.

마찬가지로 소개할 수도 있습니다.paste주문하다모든 POSIX 호환 시스템에 동일한 효과가 있습니다.

read junk a b junk < <(find -mtime -2 | paste -s)

paste -s입력을 탭으로 구분된 단일 줄로 변환하여 read다시 처리할 수 있습니다.

일반적으로 주 명령을 여러 번 실행하려는 경우(여기에서는 불필요함) 다음을 사용할 수 있습니다.sed용이하게:

find | sed -n 2p

-n일반 출력 억제를 사용하고 인쇄를 위해 라인 2를 선택하면 출력의 두 번째 라인만 인쇄됩니다 p. 동일한 효과를 얻기 head위해 이들을 함께 연결할 수도 있습니다 . 이는 매우 긴 파일에서 더 효율적일 수 있습니다.tail

위의 모든 내용은 두 번째와 세 번째 줄을 및 에 저장하는 a것과 동일한 효과를 가지며 b여전히 파일에 공백, 탭, 줄 바꿈 또는 기타 문자가 없다고 가정합니다.입력 필드 구분 기호( IFS)모든 파일 이름의 값입니다.


하지만 출력 순서에 유의하세요.find정의되지 않았으므로 "두 번째 파일"은 정렬을 위해 다른 방법으로 구성하지 않는 한 실제로 유용한 식별자가 아닙니다. 대부분의 경우 생성 순서에 가까울 수 있지만 전부는 아닙니다.

답변2

통과하면 bash 4.x사용할 수 있습니다지도 파일:

$ mapfile -t <<< "$(find -mtime -2)"
$ printf "%s\n" "${MAPFILE[0]}"
/home/user/logs/file-2014-08-22.log
$ printf "%s\n" "${MAPFILE[1]}"
/home/user/logs/file-2014-08-23.log

mapfile표준 입력의 행을 인덱스 배열 변수로 읽습니다. 기본 배열은 입니다 MAPFILE. 배열 이름을 지정할 수 있습니다.

mapfile -t array <<< "$(find -mtime -2)"

-t옵션을 사용하면 mapfile읽은 각 줄에서 후행 줄 바꿈이 제거됩니다.

답변3

알려진 수의 파일이나 코드나 명령줄에서 발견된 중복 항목으로 제한하는 대신 다음(길기는 하지만) 줄을 사용하여 각 출력에 연속적인 변수 이름을 할당할 수 있습니다 find.

줄/스크립트:

$ counter=0; for log_file in $(find -mtime -2); do echo $log_file; if [ -f $log_file ]; then ((counter++)); eval var_$counter=`readlink -f $log_file`; fi; done

줄이 제거되지 않으면 다음과 같이 출력됩니다(정상적으로 find).echo

.
./logs
./logs/file-2014-08-22.log
./logs/file-2014-08-23.log

그러나 여기서는 옵션을 사용하여 유효한 파일을 필터링합니다 if -f ....(언급한 대로).여기), 따라서 필요한 정보를 유지합니다.

$ echo $counter
2
$ echo $var_1
/home/shadowe/Videos/logs/file-2014-08-22.log
$ echo $var_2
/home/shadowe/Videos/logs/file-2014-08-23.log

따라서 시퀀스 변수에는 결과에 대한 절대 경로가 포함되어 find있으며 기존 스크립트와 쉽게 병합될 수 있습니다.

관련 정보