나는 스크립트를 만든다자바 파일 커넥터cat
및 다음 을 사용하여 sed
여러 .java
파일을 연결합니다.
#!/bin/bash
########################################################################################################################
# This file create a "MainFileName.java.output" file concatenating all java file in this directory.
# Run this script as '$ ./javaFilesConcatenator MainFileName' when "MainFileName.java" contains the main method.
########################################################################################################################
cat *.java | sed -e 's/public class/class/g;s/public interface/interface/g' >$1.java.output
sed -i "s/class $1/public class $1/g" $1.java.output
이 스크립트를 실행하려면 메인 클래스 이름을 사용자에게 입력 매개변수로 전달합니다. 메인 클래스는 이어야 public
하고 다른 클래스는 그렇지 않기 때문입니다. 메인 클래스를 public class ClassName
제외한 모든 것을 교체했습니다 .class ClassName
이제 메인 클래스 이름을 제공하지 않고도 메인 클래스를 감지할 수 있도록 스크립트를 보다 사용자 친화적으로 수정하고 싶습니다. 메인 클래스가 다른 클래스와 다르기 때문에 가능한 일인 것 같아요. 메소드 가 포함되어 있습니다 main
.
import
그리고 또 다른 요구 사항은 출력 파일의 다른 위치에서 잘라내어 문서의 시작 부분에 모든 (ig) 문을 넣어야 한다는 것입니다 . (각 파일에는 시작 부분에 일부 문이 있지만 처음에는 이러한 문을 모두 연결하지 않은 후) 시작.import java.util.Scanner;
import
또 다른 선택적 요구 사항은 유사한 줄을 모두 삭제 package com.alhelal.texpad;
하지만 word 가 포함된 주석은 삭제하지 않는다는 것입니다 package
.
제 요청을 들어드릴 수 있을까요?
답변1
스크립트 sed
는 모든 단계를 수행해야 하지만 테스트 데이터가 없기 때문에 테스트할 수 없습니다.
sed '/^[^/]*package/d
/import *java\./{p;d;}
H;/void main()/{g;s/.*\n[[:space:]]*public/& public/;h;}
$!d;g;s/public class/class/g' *.java
이 스크립트의 주요 개념:
- 여러 파일 이름을 에 전달할 수 있습니다
sed
. 파일 이름은 한 줄씩 읽혀집니다.sed
한 파일과 다른 파일이 언제 시작되는지는 알 수 없지만 어쨌든 여기서는 필요하지 않습니다. - 행 단위로 작업 하므로
sed
나중에 필요한 행을 저장하려면 약간의 메모리가 필요합니다. 이는 파일을 재정렬하는 데 필요합니다(모든 가져오기는 출력 위에 표시됩니다). 에서sed
이 메모리는 공간을 보유하고 있습니다. 클립보드처럼 생각하세요. 스크립트의 모든 루프에서 새 줄로 패턴 공간을 덮어쓰더라도 보유 버퍼는 변경되지 않습니다. 복사 패턴 공간을 예약된 공간으로 사용하거나h
다시 복사하거나g
둘 다 교환할 수 있습니다x
.H
패턴 공간의 내용을 예약된 공간(사이에 줄 바꿈 포함)에 추가하고 그 반대의 경우도 마찬가지입니다g
. 따라서 출력 상단에 원하는 줄은p
즉시 인쇄(사용)되고 다른 모든 줄은 예약된 공간에 추가됩니다. 모든 행의 끝에 도달하면 예약된 공간에 수집된 행을 처리할 수 있습니다. - 하나만 빼고 모두
public
삭제해야 합니다. 나는 이를 수행하기 위해 트릭을 사용합니다.main
메서드를 만날 때마다 마지막 클래스가 공개로 유지되는 클래스라는 것을 알기 때문에 이를 공개로 표시해야 합니다. 하지만 어떻게? 트릭:public
거기에 두 번째 클래스를 추가하여 를 얻습니다 . 따라서 나중에 모두 로public class fooClass ... public public class thisIsTheMainClass ... public class barClass
바꾸면 메인 클래스에는 여전히 하나의 속성이 남게 됩니다. 두 번째 추가는 세 번째 줄에서 발생합니다(예약된 공간을 사용하려면 패턴 공간에 복사한 다음 다시 복사해야 함).public class
class
public
public
- 기억해야 할 한 가지:
sed
명령 앞에 "주소"를 붙여 해당 주소와 일치하는 행에 대해서만 실행되도록 할 수 있습니다. 주소는 줄을 일치시키기 위해 슬래시로 묶인 정규식 패턴일 수 있습니다. 이는 스크립트의 처음 세 줄에 사용됩니다. 또는 선택한 주소가 반전되어 마지막 줄을 제외한 모든 항목에서 선택이 수행되는$
스크립트의 네 번째 줄과 같은 줄 번호 또는 마지막 줄일 수 있습니다 . 주소 뒤에 대괄호로 묶인 명령이 오면 스크립트의 두 번째 및 세 번째 줄에서와 같이 내부의 모든 명령은 해당 주소에 대해서만 실행됩니다.!
d
{}
스크립트 세부정보:
/^[^/]*package/d
해당 단어를 포함package
하고 앞에 슬래시가 없는 모든 줄을 삭제합니다. 이것이 당신이 원하는 것이기를 바랍니다./import *java\./{p;d;}
Java 가져오기를 사용하여 모든 행을 즉시 인쇄하고 추가 처리를 중지합니다.H
인쇄하는 대신 예약된 공간에 다른 모든 줄을 수집합니다. 이것이 출력 시작 시 모든 import를 수집하는 방법입니다./void main()/{g;s/.*\n[[:space:]]*public/& public/;h;}
: 이main
방법이 만족 되면g
지금까지 수집된 라인을 패턴 공간으로 이동합니다. 이 명령은s
마지막으로 발생한 라인의 시작 부분을 검색하여 추가합니다. 수정된 버퍼를 예약된 공간으로 다시 전송public
public
h
$!d
이것이 마지막 줄이 아니면 추가 조치가 필요하지 않습니다.g;s/public class/class/g'
우리가 수집한 가져오지 않은 모든 라인을 패턴 공간으로 이동하고public
클래스에서 모든 라인을 제거합니다. 메인 클래스에 두 번째 클래스를 추가하면public
메인 클래스는 공개 상태로 유지됩니다.
일반적으로 일부 입력(주석의 식별자 또는 키워드)을 사용하여 이러한 스크립트를 중단할 수 있습니다.
답변2
먼저 기본 메소드를 찾으십시오. 파일 basename은 클래스 이름입니다.
CLASS=$(basename -s .java $(grep -l 'public static void main' *.java))
그런 다음 모든 가져오기를 추출하고 정렬한 후 uniq
다른 가져오기와 일치하는 와일드카드 가져오기가 없다고 가정합니다.
sed -n '/^[ \t]*import /p' *.java | sort | uniq > $CLASS.java.output
그런 다음 Java 파일을 처리하여 가져오기 및 패키지를 추출합니다.
grep -hv '^[ \t]*import \|^[ \t]*package' *.java | sed -e 's/public class/class/g;s/public interface/interface/g' >>$CLASS.java.output
또 다른 방법은 순수 sed입니다.
sed -e '/^[ \t]*\(import\|package\)/d;s/public class/class/g;s/public interface/interface/g' .java >>$CLASS.java.output
그런 다음 공개 수업을 재개하고 싶습니다.
sed -i "s/class $CLASS/public class $CLASS/g" $CLASS.java.output
여기에는 bashism이 없기 때문에 shebang에서 bash를 사용할 필요가 없습니다( #!/bin/sh
충분합니다).
또한 동일한 솔루션과 마찬가지로 cat-pipe
이 작업을 수행 sed
할 필요는 없지만 대신 첫 번째 솔루션에서만 실행 됩니다. 프로세스 수가 적을수록 좋습니다.sed -e 's/.../.../' *.java
cat *.java | sed -e 's/.../.../'
sed
cat
sed