나는 이것을 자주한다
paste <(cut -d, -f1 file1.csv) <(cut -d, -f1 file2.csv)
여러 파일에 대해 이는 매우 지루한 작업입니다.
예를 들어 와일드카드를 통해 이 프로세스를 자동화할 수 있습니까? cut
결과를 저장할 수 있어요
typeset -A cut_results
for f in file*.csv; do
cut_results[$f]="$(cut -d, -f1 $f)"
done
하지만 거기에서 어떻게 가는지 모르겠습니다.
답변1
특히 와일드카드를 통해 이를 자동화할 수 있습니다.e
글로벌 예선, plus eval
, 그러나 보기에 좋지 않고 참조하기 까다롭습니다.
eval paste *.csv(e\''REPLY="<(cut -d, -f1 $REPLY)"'\')
- 그 사이의 부분은
\'…\'
각 일치 항목에 대해 전 세계적으로 실행되는 일부 코드입니다.REPLY
일치하도록 설정된 변수로 수행 되며 , 수정이 가능합니다. - glob을 구문 분석할 때 확장되지 않도록 코드를 작은따옴표로 묶었습니다.
- 일치하는 경우 코드는
REPLY="<(cut -d, -f1 $REPLY)"
문자열을 생성합니다. 코드 실행 시 대체된 값 외에는 등호 뒤의 부분이 확장되지 않도록 큰따옴표가 필요합니다.<(cut -d, -f1 file1.csv)
file1.csv
e
REPLY
- 각 와일드카드 파일은 문자열로 대체되므로
기능의 복잡성을 숨기는 것이 좋습니다. 최소한의 테스트를 거쳤습니다.
function map {
emulate -LR zsh
local cmd pre
cmd=()
while [[ $# -ne 0 && $1 != "--" ]]; do
cmd+=($1)
shift
done
if ((!$#)); then
echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
return 125
fi
shift
while [[ $# -ne 0 && $1 != "--" ]]; do
pre+="${(q)1} "
shift
done
if ((!$#)); then
echo >&2 "Usage: $0: COMMAND [ARGS...] -- PREPROCESSOR [ARGS...] -- FILES..."
return 125
fi
shift
eval "${(@q)cmd}" "<($pre${(@q)^@})"
}
사용 예(구문은 다음을 상기시킵니다 zargs
):
map paste -- cut -d, -f1 -- *.csv
답변2
나는 당신의 첫 번째 줄이 단순한 한 줄짜리만큼 좋다고 생각합니다.
이름이 다른 여러 파일이 있는 경우 간단한 기록 확장 "치트"를 사용하여 중복 입력을 줄일 수 있습니다.
첫 번째 실행<(cut -d, -f1
후행 공백에 유의하세요. 또한 이 명령은 Ctrl- 를 누르기만 하면 보조 프롬프트가 표시된다는 점에 유의하세요 C. 유일한 것은 역사에 추가하는 것입니다.
다음 실행paste !!file1.csv) !!file2.csv)
!!
후행 공백을 포함하여 이전 명령 실행의 전체 내용으로 확장 됩니다 . 후행 닫는 괄호를 잊어버린 경우 보조 프롬프트가 표시됩니다. 이 경우 Ctrl-를 입력 C하고 다시 시도하세요.
조금 낡았지만 일회용으로 사용하기에는 충분합니다. 이 작업을 자주 수행하면 bash 함수를 작성할 수 있습니다.
답변3
노력하다앗
awk '{L[FNR]=L[FNR] $1 "\t"}END{for(i=1;i<=FNR;i++)print L[i]}' *.csv
또는반죽그리고sed
paste *.csv | sed 's/ [^\t]*//g'
답변4
귀하의 주장이 다음과 같다고 가정하면 "$@"
다음과 같습니다.
eval "paste $(printf "<( cut -d, -f1 %q ) " "$@")"
그것은 이루어져야합니다.