쉘 스크립트를 사용하여 여러 클래스가 있는 Java 파일에서 기본 클래스 이름을 감지하는 방법은 무엇입니까?

쉘 스크립트를 사용하여 여러 클래스가 있는 Java 파일에서 기본 클래스 이름을 감지하는 방법은 무엇입니까?

나는 스크립트를 만든다자바 파일 커넥터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 classclasspublicpublic
  • 기억해야 할 한 가지: sed명령 앞에 "주소"를 붙여 해당 주소와 일치하는 행에 대해서만 실행되도록 할 수 있습니다. 주소는 줄을 일치시키기 위해 슬래시로 묶인 정규식 패턴일 수 있습니다. 이는 스크립트의 처음 세 줄에 사용됩니다. 또는 선택한 주소가 반전되어 마지막 줄을 제외한 모든 항목에서 선택이 수행되는 $스크립트의 네 번째 줄과 같은 줄 번호 또는 마지막 줄일 수 있습니다 . 주소 뒤에 대괄호로 묶인 명령이 오면 스크립트의 두 번째 및 세 번째 줄에서와 같이 내부의 모든 명령은 해당 주소에 대해서만 실행됩니다.!d{}

스크립트 세부정보:

  • /^[^/]*package/d해당 단어를 포함 package하고 앞에 슬래시가 없는 모든 줄을 삭제합니다. 이것이 당신이 원하는 것이기를 바랍니다.
  • /import *java\./{p;d;}Java 가져오기를 사용하여 모든 행을 즉시 인쇄하고 추가 처리를 중지합니다.
  • H인쇄하는 대신 예약된 공간에 다른 모든 줄을 수집합니다. 이것이 출력 시작 시 모든 import를 수집하는 방법입니다.
  • /void main()/{g;s/.*\n[[:space:]]*public/& public/;h;}: 이 main방법이 만족 되면 g지금까지 수집된 라인을 패턴 공간으로 이동합니다. 이 명령은 s마지막으로 발생한 라인의 시작 부분을 검색하여 추가합니다. 수정된 버퍼를 예약된 공간으로 다시 전송publicpublich
  • $!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/.../.../' *.javacat *.java | sed -e 's/.../.../'sedcatsed

관련 정보